/*
* RapidMiner
*
* Copyright (C) 2001-2008 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.processeditor;
import java.awt.BorderLayout;
import java.util.Properties;
import javax.swing.Icon;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
import javax.swing.JTabbedPane;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import com.rapidminer.gui.MainFrame;
import com.rapidminer.gui.RapidMinerGUI;
import com.rapidminer.gui.operatortree.OperatorTree;
import com.rapidminer.gui.properties.OperatorPropertyTable;
import com.rapidminer.gui.properties.PropertyTable;
import com.rapidminer.gui.properties.SettingsChangeListener;
import com.rapidminer.gui.tools.ExtendedJScrollPane;
import com.rapidminer.gui.tools.ExtendedJTabbedPane;
import com.rapidminer.gui.tools.SwingTools;
import com.rapidminer.operator.Operator;
import com.rapidminer.tools.Tools;
/**
* Displays the {@link OperatorTree} and a {@link PropertyTable} in a SplitPane.
* This tree view is the main process editor of the RapidMiner GUI. The left side
* shows the current operator tree. On the right side the parameters for the
* currently selected operators are shown.
*
* @author Ingo Mierswa
* @version $Id: MainProcessEditor.java,v 1.11 2008/05/09 19:23:16 ingomierswa Exp $
*/
public class MainProcessEditor extends JSplitPane implements ProcessEditor, ChangeListener, SettingsChangeListener {
private static final long serialVersionUID = -2503689886544116347L;
public static final int PARAMETERS = 0;
public static final int XML = 1;
public static final int COMMENT = 2;
public static final int NEW_OPERATOR = 3;
private static final String OPERATOR_TREE_ICON_NAME = "branch.png";
private static final String PROPERTY_ICON_NAME = "form_blue_edit.png";
private static final String XML_ICON_NAME = "text_code.png";
private static final String COMMENT_ICON_NAME = "document_text.png";
private static final String NEW_OPERATOR_ICON_NAME = "element_new.png";
private static Icon operatorTreeIcon = null;
private static Icon propertyIcon = null;
private static Icon xmlIcon = null;
private static Icon commentIcon = null;
private static Icon newOperatorIcon = null;
static {
operatorTreeIcon = SwingTools.createIcon("16/" + OPERATOR_TREE_ICON_NAME);
propertyIcon = SwingTools.createIcon("16/" + PROPERTY_ICON_NAME);
xmlIcon = SwingTools.createIcon("16/" + XML_ICON_NAME);
commentIcon = SwingTools.createIcon("16/" + COMMENT_ICON_NAME);
newOperatorIcon = SwingTools.createIcon("16/" + NEW_OPERATOR_ICON_NAME);
}
private OperatorTree operatorTree;
private JTabbedPane operatorTreeTabs = new ExtendedJTabbedPane();
private JTabbedPane editorTabs = new ExtendedJTabbedPane();
private OperatorPropertyTable propertyTable;
private XMLEditor xmlEditor;
private CommentEditor commentEditor;
private NewOperatorEditor newOperatorEditor;
private JLabel propertyMessageLabel = new JLabel();
private int lastIndex = 0;
private MainFrame mainFrame;
public MainProcessEditor(MainFrame mainFrame) {
super(HORIZONTAL_SPLIT);
// will cause the tree half to keep fixed size during resizing
setResizeWeight(0.0);
setBorder(null);
this.mainFrame = mainFrame;
this.operatorTree = new OperatorTree(mainFrame);
this.operatorTree.setBorder(null);
this.propertyTable = new OperatorPropertyTable(mainFrame, this.propertyMessageLabel);
this.xmlEditor = new XMLEditor(mainFrame);
this.commentEditor = new CommentEditor();
this.newOperatorEditor = new NewOperatorEditor();
JScrollPane treeScrollPane = new ExtendedJScrollPane(operatorTree);
treeScrollPane.setBorder(null);
operatorTreeTabs.addTab("Operator Tree", operatorTreeIcon, treeScrollPane, "The operator tree of the current process.");
add(operatorTreeTabs);
// create tabs
JPanel propertyPanel = new JPanel(new BorderLayout());
this.propertyTable.setOpaque(false);
propertyPanel.add(this.propertyTable, BorderLayout.CENTER);
propertyPanel.add(this.propertyMessageLabel, BorderLayout.SOUTH);
JScrollPane propertyPane = new ExtendedJScrollPane(propertyPanel);
editorTabs.addTab("Parameters", propertyIcon, propertyPane, "Shows the parameters of the currently selected operator.");
editorTabs.addTab("XML", xmlIcon, this.xmlEditor, "Shows the XML definition of the current process setup.");
editorTabs.addTab("Comment", commentIcon, this.commentEditor, "Shows a comment editor for the currently selected operator.");
editorTabs.addTab("New Operator", newOperatorIcon, newOperatorEditor, "Shows a grouped view of all available operators for dragging them into the operator tree.");
add(editorTabs);
// important that this method is invoked as last
editorTabs.addChangeListener(this);
}
/** Currently, the only process editor beside the operator tree is the XML editor. Therefore,
* this editor is returns if the index matches XML and null is returned otherwise. */
private ProcessEditor getProcessEditor(int index) {
switch (index) {
case XML:
return xmlEditor;
case COMMENT:
return commentEditor;
default:
return null;
}
}
public void setGroupSelectionDivider(int pos) {
this.newOperatorEditor.setDividerLocation(pos);
}
public int getGroupSelectionDivider() {
return this.newOperatorEditor.getDividerLocation();
}
public void processChanged(Operator operator) {
this.operatorTree.setOperator(operator);
this.propertyTable.setOperator(null);
this.xmlEditor.processChanged(operator);
this.commentEditor.setCurrentOperator(null);
}
public void setCurrentOperator(Operator current) {
this.propertyTable.setOperator(current);
this.xmlEditor.setCurrentOperator(current);
this.commentEditor.setCurrentOperator(current);
}
public void validateProcess() {}
public OperatorTree getOperatorTree() {
return this.operatorTree;
}
public OperatorPropertyTable getPropertyTable() {
return this.propertyTable;
}
public XMLEditor getXMLEditor() {
return this.xmlEditor;
}
public boolean isXMLViewActive() {
return (editorTabs.getSelectedIndex() == XML);
}
public boolean isDescriptionViewActive() {
return (editorTabs.getSelectedIndex() == COMMENT);
}
public void changeToXMLEditor() {
this.editorTabs.setSelectedIndex(XML);
}
public void changeFromNewOperator2ParameterEditor() {
if (this.editorTabs.getSelectedIndex() == NEW_OPERATOR)
this.editorTabs.setSelectedIndex(PARAMETERS);
}
public void stateChanged(ChangeEvent e) {
// important in order to save the last user editing:
getPropertyTable().stopCurrentEditing();
int currentIndex = editorTabs.getSelectedIndex();
if (lastIndex == currentIndex) {
return;
}
try {
if (currentIndex >= 0) {
ProcessEditor lastEditor = getProcessEditor(lastIndex);
if (lastEditor != null) {
lastEditor.validateProcess();
}
}
ProcessEditor newEditor = getProcessEditor(currentIndex);
if (newEditor != null) {
newEditor.processChanged(RapidMinerGUI.getMainFrame().getProcess().getRootOperator());
}
lastIndex = currentIndex;
} catch (Exception ex) {
switch (JOptionPane.showConfirmDialog(this, ex.toString() + Tools.getLineSeparator() + "Cancel to ignore changes, Ok to go on editing.", "Error", JOptionPane.OK_CANCEL_OPTION, JOptionPane.ERROR_MESSAGE)) {
case JOptionPane.OK_OPTION:
editorTabs.setSelectedIndex(lastIndex);
break;
default:
case JOptionPane.CANCEL_OPTION:
ProcessEditor lastEditor = getProcessEditor(lastIndex);
if (lastEditor != null) {
lastEditor.processChanged(RapidMinerGUI.getMainFrame().getProcess().getRootOperator());
}
break;
}
}
this.mainFrame.enableActions();
}
public void settingsChanged(Properties properties) {}
}