/*
* 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.processeditor.results;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Insets;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.text.DateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import javax.swing.Action;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import com.rapidminer.Process;
import com.rapidminer.ProcessLocation;
import com.rapidminer.gui.RapidMinerGUI;
import com.rapidminer.gui.look.ui.ExtensionButtonUI;
import com.rapidminer.gui.tools.ResourceAction;
import com.rapidminer.gui.tools.SwingTools;
import com.rapidminer.operator.IOObject;
import com.rapidminer.tools.Tools;
/** Summarizes the result of a single process execution.
*
* @author Simon Fischer
*
*/
public class ProcessExecutionResultOverview extends JPanel {
private static final Color[][] COLORS = {
{ SwingTools.LIGHTEST_BLUE, SwingTools.LIGHT_BLUE },
{ SwingTools.LIGHTEST_YELLOW, SwingTools.LIGHT_YELLOW }
};
private static final Map<String,Color[]> processLocationToColor = new HashMap<String,Color[]>();
private static int lastUsedProcessColor = 0;
private final Action RESTORE_PROCESS = new ResourceAction(true, "resulthistory.restore_process") {
private static final long serialVersionUID = 1L;
@Override
public void actionPerformed(ActionEvent e) {
try {
Process process = new Process(ProcessExecutionResultOverview.this.process);
process.setProcessLocation(processLocation);
RapidMinerGUI.getMainFrame().setProcess(process, true);
} catch (Exception e1) {
SwingTools.showSimpleErrorMessage("cannot_restore_history_process", e1);
}
}
};
private final Action REMOVE_FROM_HISTORY = new ResourceAction(true, "resulthistory.remove") {
private static final long serialVersionUID = 1L;
@Override
public void actionPerformed(ActionEvent e) {
parent.removeProcessOverview(ProcessExecutionResultOverview.this);
}
};
private final JButton removeButton = new JButton(REMOVE_FROM_HISTORY);
private final JButton restoreButton = new JButton(RESTORE_PROCESS);
private static final long serialVersionUID = 1L;
private final String process;
private final ProcessLocation processLocation;
private final Date terminationTime;
private final long executionTime;
private boolean expanded = false;
private final List<SingleResultOverview> results = new LinkedList<SingleResultOverview>();
private final ResultOverview parent;
private final JLabel headerLabel;
private int columns;
private int rows;
public ProcessExecutionResultOverview(ResultOverview parent, Process process, List<IOObject> results, String statusMessage) {
setOpaque(false);
setLayout(null);
setBackground(Color.WHITE);
restoreButton.setUI(new ExtensionButtonUI());
restoreButton.setMargin(new Insets(0, 0, 0, 0));
restoreButton.setText(null);
restoreButton.setOpaque(false);
add(restoreButton);
removeButton.setUI(new ExtensionButtonUI());
removeButton.setMargin(new Insets(0, 0, 0, 0));
removeButton.setText(null);
removeButton.setOpaque(false);
add(removeButton);
Color[] colors = getColorFor(process);
RapidBorder border = new RapidBorder(colors[1], 10, 18);
setBackground(colors[0]);
setBorder(BorderFactory.createCompoundBorder(BorderFactory.createMatteBorder(5, 5, 10, 5, Color.WHITE), border));
this.parent = parent;
this.process = process.getRootOperator().getXML(false);
this.processLocation = process.getProcessLocation();
this.terminationTime = new Date();
executionTime = System.currentTimeMillis() - process.getRootOperator().getStartTime();
String processName;
if (process.getProcessLocation() != null) {
processName = process.getProcessLocation().getShortName();
} else {
processName = process.getRootOperator().getName();
}
StringBuilder b = new StringBuilder();
b.append("<html><strong>");
b.append(processName);
b.append("</strong> (");
b.append(results.size());
b.append(" results. <small>");
b.append(statusMessage);
b.append("</small>)<br/>Completed: ");
b.append(DateFormat.getDateTimeInstance().format(terminationTime));
b.append(" (execution time: ").append(Tools.formatDuration(executionTime)).append(")");
b.append("</html>");
headerLabel = new JLabel(b.toString());
headerLabel.setFont(headerLabel.getFont().deriveFont(14f));
add(headerLabel);
headerLabel.setBounds(10, 2, 500, 40);
int i = 0;
for (IOObject result : results) {
SingleResultOverview singleOverview = new SingleResultOverview(result, process, i);
this.results.add(singleOverview);
i++;
}
addMouseListener(new MouseAdapter() {
@Override
public void mouseReleased(MouseEvent e) {
if (e.isPopupTrigger()) {
showContextMenu(e.getPoint());
}
}
@Override
public void mousePressed(MouseEvent e) {
if (e.isPopupTrigger()) {
showContextMenu(e.getPoint());
}
}
@Override
public void mouseClicked(MouseEvent e) {
if (e.isPopupTrigger()) {
showContextMenu(e.getPoint());
} else {
setExpanded(!expanded);
}
}
});
}
private void setExpanded(boolean expanded) {
if (expanded != this.expanded) {
this.expanded = expanded;
for (SingleResultOverview overview : results) {
if (expanded) {
add(overview);
} else {
remove(overview);
}
}
getParent().doLayout();
revalidate();
// getParent().invalidate();
}
}
void recomputeLayout() {
int parentWidth = parent.getWidth();
Dimension totalSize;
if (!expanded) {
totalSize = new Dimension(parentWidth - 30, 50);
} else {
int freeWidth = parentWidth - 30;
this.columns = (int)Math.floor((double)freeWidth / SingleResultOverview.MIN_WIDTH);
this.rows = (int)Math.ceil((double)results.size() / columns);
//int individualWidth = (int)((double)freeWidth / columns - 10);
int individualWidth = SingleResultOverview.MIN_WIDTH-10;
int i = 0;
for (SingleResultOverview overview : results) {
int row = i / columns;
int col = i % columns;
overview.setBounds(10 + col*individualWidth, 45 + row * SingleResultOverview.MIN_HEIGHT, individualWidth-5, SingleResultOverview.MIN_HEIGHT-10);
i++;
}
totalSize = new Dimension(parentWidth - 30, rows * SingleResultOverview.MIN_HEIGHT + 50);
}
// restoreButton.setOpaque(false);
restoreButton.setBounds(new Rectangle(
(int)totalSize.getWidth() - 48 - 5,
6,
(int)restoreButton.getPreferredSize().getWidth(),
(int)restoreButton.getPreferredSize().getHeight()));
removeButton.setBounds(new Rectangle(
(int)totalSize.getWidth() - 24-5,
6,
(int)restoreButton.getPreferredSize().getWidth(),
(int)restoreButton.getPreferredSize().getHeight()));
setSize(totalSize);
setPreferredSize(totalSize);
setMinimumSize(totalSize);
setMaximumSize(totalSize);
}
private void showContextMenu(Point point) {
JPopupMenu menu = new JPopupMenu();
menu.add(RESTORE_PROCESS);
menu.add(REMOVE_FROM_HISTORY);
menu.add(parent.CLEAR_HISTORY_ACTION);
menu.show(this, (int)point.getX(), (int)point.getY());
}
private Color[] getColorFor(Process process) {
String loc = process.getProcessLocation() == null ? null : process.getProcessLocation().toString();
Color[] colors = processLocationToColor.get(loc);
if (colors == null) {
colors = COLORS[((lastUsedProcessColor++) % COLORS.length)];
processLocationToColor.put(loc, colors);
}
return colors;
}
}