/* * 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.Component; import java.awt.Graphics2D; import java.awt.Point; import java.awt.event.ActionEvent; import java.awt.event.ComponentAdapter; import java.awt.event.ComponentEvent; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.awt.image.BufferedImage; import java.lang.ref.SoftReference; import java.util.List; import javax.swing.Action; import javax.swing.JEditorPane; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JPopupMenu; import javax.swing.JScrollPane; import javax.swing.text.html.HTMLEditorKit; import javax.swing.text.html.StyleSheet; import com.rapidminer.Process; import com.rapidminer.example.ExampleSet; import com.rapidminer.gui.RapidMinerGUI; import com.rapidminer.gui.flow.ProcessRenderer; import com.rapidminer.gui.renderer.DefaultTextRenderer; import com.rapidminer.gui.renderer.Renderer; import com.rapidminer.gui.renderer.RendererService; import com.rapidminer.gui.tools.ExtendedHTMLJEditorPane; import com.rapidminer.gui.tools.ProgressThread; import com.rapidminer.gui.tools.ResourceAction; import com.rapidminer.gui.tools.SwingTools; import com.rapidminer.operator.IOContainer; import com.rapidminer.operator.IOObject; import com.rapidminer.operator.ResultObject; import com.rapidminer.operator.ports.InputPort; import com.rapidminer.operator.ports.metadata.MetaData; import com.rapidminer.report.Renderable; import com.rapidminer.report.Reportable; import com.rapidminer.repository.Entry; import com.rapidminer.repository.IOObjectEntry; import com.rapidminer.repository.RepositoryLocation; /** * Displays an overview of a single IOObject. Does not remember the IOObject itself. * * @author Simon Fischer * */ public class SingleResultOverview extends JPanel { private static final long serialVersionUID = 1L; private final JLabel title; private final Component main; private String repositoryLocation = null; private SoftReference<ResultObject> ioObject; static final int MIN_HEIGHT = 300; static final int MIN_WIDTH = 300; private static final int MAX_RESULT_STRING_LENGTH = 2048; private final Action RESTORE_FROM_REPOSITORY = new ResourceAction("resulthistory.restore_data") { private static final long serialVersionUID = 1L; @Override public void actionPerformed(ActionEvent e) { final ProgressThread downloadProgressThread = new ProgressThread("download_from_repository") { public void run() { try { RepositoryLocation location = new RepositoryLocation(repositoryLocation); Entry entry = location.locateEntry(); if (entry instanceof IOObjectEntry) { IOObjectEntry data = (IOObjectEntry) entry; ResultObject result = (ResultObject) data.retrieveData(this.getProgressListener()); result.setSource(data.getLocation().toString()); RapidMinerGUI.getMainFrame().getResultDisplay().showResult(result); } else { SwingTools.showSimpleErrorMessage("cannot_fetch_data_from_repository", "Not an IOObject."); } } catch (Exception e1) { SwingTools.showSimpleErrorMessage("cannot_fetch_data_from_repository", e1); } } }; downloadProgressThread.start(); } }; private final Action OPEN_DATA = new ResourceAction("resulthistory.open_data") { private static final long serialVersionUID = 1L; @Override public void actionPerformed(ActionEvent e) { ResultObject referenced = ioObject.get(); if (referenced != null) { RapidMinerGUI.getMainFrame().getResultDisplay().showResult(referenced); } } }; public SingleResultOverview(IOObject result, Process process, int resultIndex) { setLayout(null); setOpaque(false); MetaData metaData = MetaData.forIOObject(result, true); setBorder(new RapidBorder(ProcessRenderer.getColorFor(metaData), 15, 35)); setBackground(Color.WHITE); if (result instanceof ResultObject) { this.ioObject = new SoftReference<ResultObject>((ResultObject) result); } if (process.getRootOperator().getSubprocess(0).getInnerSinks().getNumberOfPorts() > resultIndex) { InputPort resultPort = process.getRootOperator().getSubprocess(0).getInnerSinks().getPortByIndex(resultIndex); IOObject other = resultPort.getAnyDataOrNull(); if (result == other) { // make sure result does not come from collecting unconnected outputs, but is really // from inner sink if (process.getContext().getOutputRepositoryLocations().size() > resultIndex) { repositoryLocation = process.getContext().getOutputRepositoryLocations().get(resultIndex).toString(); } } } String name = result.getClass().getSimpleName(); if (result instanceof ExampleSet) { main = makeMainLabel("<html>" + metaData.getDescription() + "</html>"); name = ((ResultObject) result).getName(); } else { name = RendererService.getName(result.getClass()); List<Renderer> renderers = RendererService.getRenderers(name); if (renderers.isEmpty()) { main = makeTextRenderer(result); } else { Component component = null; for (Renderer renderer : renderers) { if (!(renderer instanceof DefaultTextRenderer)) { IOContainer dummy = new IOContainer(); int imgWidth = MIN_WIDTH - 10; int imgHeight = MIN_HEIGHT - 65; Reportable reportable = renderer.createReportable(result, dummy, imgWidth, imgHeight); if (reportable instanceof Renderable) { Renderable renderable = (Renderable) reportable; renderable.prepareRendering(); int preferredWidth = renderable.getRenderWidth(800); int preferredHeight = renderable.getRenderHeight(800); final BufferedImage img = new BufferedImage(imgWidth, imgHeight, BufferedImage.TYPE_INT_RGB); Graphics2D graphics = (Graphics2D) img.getGraphics(); graphics.setColor(Color.WHITE); graphics.fillRect(0, 0, imgWidth, imgHeight); double scale = Math.min((double) imgWidth / (double) preferredWidth, (double) imgHeight / (double) preferredHeight); graphics.scale(scale, scale); renderable.render(graphics, preferredWidth, preferredHeight); component = new JPanel() { private static final long serialVersionUID = 1L; @Override protected void paintComponent(java.awt.Graphics g) { g.drawImage(img, 0, 0, null); } }; break; } } else { component = makeTextRenderer(result); break; } } if (component == null) { main = makeTextRenderer(result); } else { main = component; } } } StringBuilder b = new StringBuilder(); b.append("<html><strong>").append(name); b.append("</strong> (").append(result.getSource()).append(")"); if (repositoryLocation != null) { b.append("<br/><small>").append(repositoryLocation).append("</small>"); } else { b.append("<br/><small>Result not stored in repository.</small>"); } b.append("</html>"); title = new JLabel(b.toString()); add(title); title.setBounds(5, 0, MIN_WIDTH - 15, 40); add(main); main.setBounds(5, 45, MIN_WIDTH - 10, MIN_HEIGHT - 65); 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()); } } }); addComponentListener(new ComponentAdapter() { @Override public void componentResized(ComponentEvent e) { main.setBounds(5, 45, getWidth() - 10, getHeight() - 65); } }); } private Component makeTextRenderer(IOObject result) { if (result instanceof ResultObject) { String resultString = ((ResultObject) result).toResultString(); if (resultString.length() > MAX_RESULT_STRING_LENGTH) { resultString = resultString.substring(0, MAX_RESULT_STRING_LENGTH); } return makeMainLabel("<html><pre>" + resultString + "</pre></html>"); } else { return makeMainLabel("No information available."); } } private Component makeMainLabel(String text) { JEditorPane label = new ExtendedHTMLJEditorPane("text/html", text); StyleSheet css = ((HTMLEditorKit) label.getEditorKit()).getStyleSheet(); css.addRule("body {font-family:Sans;font-size:11pt}"); css.addRule("h3 {margin:0; padding:0}"); css.addRule("h4 {margin-bottom:0; margin-top:1ex; padding:0}"); css.addRule("p {margin-top:0; margin-bottom:1ex; padding:0}"); css.addRule("ul {margin-top:0; margin-bottom:1ex; list-style-image: url(" + getClass().getResource("/com/rapidminer/resources/icons/modern/help/circle.png") + ")}"); css.addRule("ul li {padding-bottom: 2px}"); css.addRule("li.outPorts {padding-bottom: 0px}"); css.addRule("ul li ul {margin-top:0; margin-bottom:1ex; list-style-image: url(" + getClass().getResource("/com/rapidminer/resources/icons/modern/help/line.png") + ")"); css.addRule("li ul li {padding-bottom:0}"); // label.setOpaque(false); label.setEditable(false); label.setBackground(Color.WHITE); // label.setVerticalTextPosition(SwingConstants.TOP); // label.setHorizontalTextPosition(SwingConstants.LEFT); JScrollPane pane = new JScrollPane(label); pane.setBackground(Color.WHITE); pane.setBorder(null); return pane; } protected void showContextMenu(Point point) { JPopupMenu menu = new JPopupMenu(); boolean empty = true; if (repositoryLocation != null) { menu.add(RESTORE_FROM_REPOSITORY); empty = false; } if ((ioObject != null) && (ioObject.get() != null)) { menu.add(OPEN_DATA); empty = false; } if (!empty) { menu.show(this, (int) point.getX(), (int) point.getY()); } } }