Java tutorial
/* * Copyright 2014 JBoss Inc * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.optaplanner.benchmark.impl.aggregator.swingui; import java.awt.BorderLayout; import java.awt.Desktop; import java.awt.FlowLayout; import java.awt.GridLayout; import java.awt.event.ActionEvent; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.LinkedHashMap; import java.util.List; import java.util.Locale; import java.util.Map; import java.util.concurrent.ExecutionException; import javax.swing.AbstractAction; import javax.swing.BorderFactory; import javax.swing.ImageIcon; import javax.swing.JButton; import javax.swing.JCheckBox; import javax.swing.JComponent; import javax.swing.JDialog; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JProgressBar; import javax.swing.JScrollPane; import javax.swing.JTextArea; import javax.swing.JTextField; import javax.swing.JTextPane; import javax.swing.SwingWorker; import javax.swing.WindowConstants; import javax.swing.event.TreeSelectionEvent; import javax.swing.event.TreeSelectionListener; import javax.swing.text.SimpleAttributeSet; import javax.swing.text.StyleConstants; import javax.swing.text.StyledDocument; import javax.swing.tree.DefaultMutableTreeNode; import javax.swing.tree.DefaultTreeModel; import javax.swing.tree.TreePath; import org.apache.commons.lang.StringUtils; import org.optaplanner.benchmark.api.PlannerBenchmarkFactory; import org.optaplanner.benchmark.config.PlannerBenchmarkConfig; import org.optaplanner.benchmark.config.report.BenchmarkReportConfig; import org.optaplanner.benchmark.impl.aggregator.BenchmarkAggregator; import org.optaplanner.benchmark.impl.aggregator.swingui.MixedCheckBox.MixedCheckBoxStatus; import org.optaplanner.benchmark.impl.result.BenchmarkResultIO; import org.optaplanner.benchmark.impl.result.PlannerBenchmarkResult; import org.optaplanner.benchmark.impl.result.ProblemBenchmarkResult; import org.optaplanner.benchmark.impl.result.SingleBenchmarkResult; import org.optaplanner.benchmark.impl.result.SolverBenchmarkResult; import org.optaplanner.benchmark.impl.statistic.common.MillisecondsSpentNumberFormat; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class BenchmarkAggregatorFrame extends JFrame { public static void createAndDisplay(PlannerBenchmarkFactory plannerBenchmarkFactory) { SwingUncaughtExceptionHandler.register(); SwingUtils.fixateLookAndFeel(); PlannerBenchmarkConfig plannerBenchmarkConfig = plannerBenchmarkFactory.getPlannerBenchmarkConfig(); BenchmarkAggregator benchmarkAggregator = new BenchmarkAggregator(); benchmarkAggregator.setBenchmarkDirectory(plannerBenchmarkConfig.getBenchmarkDirectory()); BenchmarkReportConfig benchmarkReportConfig = plannerBenchmarkConfig.getBenchmarkReportConfig(); if (benchmarkReportConfig == null) { benchmarkReportConfig = new BenchmarkReportConfig(); } benchmarkAggregator.setBenchmarkReportConfig(benchmarkReportConfig); BenchmarkAggregatorFrame benchmarkAggregatorFrame = new BenchmarkAggregatorFrame(benchmarkAggregator); benchmarkAggregatorFrame.init(); benchmarkAggregatorFrame.setVisible(true); } protected final transient Logger logger = LoggerFactory.getLogger(getClass()); private final BenchmarkAggregator benchmarkAggregator; private final BenchmarkResultIO benchmarkResultIO; private final MillisecondsSpentNumberFormat millisecondsSpentNumberFormat; private List<PlannerBenchmarkResult> plannerBenchmarkResultList; private Map<SingleBenchmarkResult, DefaultMutableTreeNode> resultCheckBoxMapping = new LinkedHashMap<SingleBenchmarkResult, DefaultMutableTreeNode>(); private Map<SolverBenchmarkResult, String> solverBenchmarkResultNameMapping = new HashMap<SolverBenchmarkResult, String>(); private CheckBoxTree checkBoxTree; private JTextArea detailTextArea; private JProgressBar generateProgressBar; private JButton generateReportButton; private JButton renameNodeButton; private boolean exitApplicationWhenReportFinished = true; public BenchmarkAggregatorFrame(BenchmarkAggregator benchmarkAggregator) { super("Benchmark aggregator"); this.benchmarkAggregator = benchmarkAggregator; benchmarkResultIO = new BenchmarkResultIO(); plannerBenchmarkResultList = Collections.emptyList(); Locale locale = benchmarkAggregator.getBenchmarkReportConfig().determineLocale(); millisecondsSpentNumberFormat = new MillisecondsSpentNumberFormat(locale); } public void init() { setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); initPlannerBenchmarkResultList(); setContentPane(createContentPane()); pack(); setLocationRelativeTo(null); } private JComponent createContentPane() { JPanel contentPane = new JPanel(new BorderLayout()); contentPane.add(createTopButtonPanel(), BorderLayout.NORTH); contentPane.add(createBenchmarkTreePanel(), BorderLayout.CENTER); contentPane.add(createDetailTextArea(), BorderLayout.SOUTH); return contentPane; } private JComponent createNoPlannerFoundTextField() { String infoMessage = "No planner benchmarks have been found in the benchmarkDirectory (" + benchmarkAggregator.getBenchmarkDirectory() + ")."; JTextPane textPane = new JTextPane(); textPane.setEditable(false); textPane.setText(infoMessage); // center info message StyledDocument styledDocument = textPane.getStyledDocument(); SimpleAttributeSet center = new SimpleAttributeSet(); StyleConstants.setAlignment(center, StyleConstants.ALIGN_CENTER); StyleConstants.setBold(center, true); styledDocument.setParagraphAttributes(0, styledDocument.getLength(), center, false); return textPane; } private JComponent createDetailTextArea() { JPanel detailPanel = new JPanel(new BorderLayout()); JLabel detailLabel = new JLabel("Details"); detailPanel.add(detailLabel, BorderLayout.NORTH); detailTextArea = new JTextArea(5, 80); detailTextArea.setEditable(false); JScrollPane detailScrollPane = new JScrollPane(detailTextArea, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED); detailPanel.add(detailScrollPane, BorderLayout.SOUTH); return detailPanel; } private JComponent createTopButtonPanel() { JPanel buttonPanel = new JPanel(new GridLayout(1, 6)); buttonPanel.add(new JButton(new ExpandAllNodesAction())); buttonPanel.add(new JButton(new CollapseAllNodesAction())); buttonPanel.add(new JButton(new MoveNodeAction(true))); buttonPanel.add(new JButton(new MoveNodeAction(false))); renameNodeButton = new JButton(new RenameNodeAction()); renameNodeButton.setEnabled(false); buttonPanel.add(renameNodeButton); buttonPanel.add(new JButton(new SwitchLevelsAction(false))); return buttonPanel; } private JComponent createBenchmarkTreePanel() { JPanel benchmarkTreePanel = new JPanel(new BorderLayout()); benchmarkTreePanel.add(new JScrollPane( plannerBenchmarkResultList.isEmpty() ? createNoPlannerFoundTextField() : createCheckBoxTree(), JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED), BorderLayout.CENTER); JPanel buttonPanelWrapper = new JPanel(new FlowLayout(FlowLayout.RIGHT)); JPanel buttonPanel = new JPanel(new GridLayout(1, 2, 10, 0)); generateReportButton = new JButton(new GenerateReportAction(this)); generateReportButton.setEnabled(false); buttonPanel.add(generateReportButton); generateProgressBar = new JProgressBar(); buttonPanel.add(generateProgressBar); buttonPanelWrapper.add(buttonPanel); benchmarkTreePanel.add(buttonPanelWrapper, BorderLayout.SOUTH); benchmarkTreePanel.setBorder(BorderFactory.createEmptyBorder(0, 0, 15, 0)); return benchmarkTreePanel; } private CheckBoxTree createCheckBoxTree() { final CheckBoxTree resultCheckBoxTree = new CheckBoxTree(initBenchmarkHierarchy(true)); resultCheckBoxTree.addTreeSelectionListener(new TreeSelectionListener() { @Override public void valueChanged(TreeSelectionEvent e) { TreePath treeSelectionPath = e.getNewLeadSelectionPath(); if (treeSelectionPath != null) { DefaultMutableTreeNode treeNode = (DefaultMutableTreeNode) treeSelectionPath .getLastPathComponent(); MixedCheckBox checkBox = (MixedCheckBox) treeNode.getUserObject(); detailTextArea.setText(checkBox.getDetail()); detailTextArea.setCaretPosition(0); renameNodeButton.setEnabled(checkBox.getBenchmarkResult() instanceof PlannerBenchmarkResult || checkBox.getBenchmarkResult() instanceof SolverBenchmarkResult); } } }); resultCheckBoxTree.addMouseListener(new MouseAdapter() { @Override public void mousePressed(MouseEvent e) { // Enable button if checked singleBenchmarkResults exist generateReportButton.setEnabled(!resultCheckBoxTree.getSelectedSingleBenchmarkNodes().isEmpty()); } }); checkBoxTree = resultCheckBoxTree; return resultCheckBoxTree; } private void initPlannerBenchmarkResultList() { plannerBenchmarkResultList = benchmarkResultIO .readPlannerBenchmarkResultList(benchmarkAggregator.getBenchmarkDirectory()); for (PlannerBenchmarkResult plannerBenchmarkResult : plannerBenchmarkResultList) { plannerBenchmarkResult.accumulateResults( benchmarkAggregator.getBenchmarkReportConfig().buildBenchmarkReport(plannerBenchmarkResult)); } } private class GenerateReportAction extends AbstractAction { private final BenchmarkAggregatorFrame parentFrame; public GenerateReportAction(BenchmarkAggregatorFrame parentFrame) { super("Generate report"); this.parentFrame = parentFrame; } public void actionPerformed(ActionEvent e) { parentFrame.setEnabled(false); generateReport(); } private void generateReport() { List<SingleBenchmarkResult> singleBenchmarkResultList = new ArrayList<SingleBenchmarkResult>(); for (Map.Entry<SingleBenchmarkResult, DefaultMutableTreeNode> entry : resultCheckBoxMapping .entrySet()) { if (((MixedCheckBox) entry.getValue().getUserObject()).getStatus() == MixedCheckBoxStatus.CHECKED) { singleBenchmarkResultList.add(entry.getKey()); } } if (singleBenchmarkResultList.isEmpty()) { JOptionPane.showMessageDialog(parentFrame, "No single benchmarks have been selected.", "Warning", JOptionPane.WARNING_MESSAGE); parentFrame.setEnabled(true); } else { generateProgressBar.setIndeterminate(true); generateProgressBar.setStringPainted(true); generateProgressBar.setString("Generating..."); GenerateReportWorker worker = new GenerateReportWorker(parentFrame, singleBenchmarkResultList); worker.execute(); } } } private class ExpandAllNodesAction extends AbstractAction { public ExpandAllNodesAction() { super("Expand all", new ImageIcon(BenchmarkAggregatorFrame.class.getResource("expandAll.png"))); setEnabled(!plannerBenchmarkResultList.isEmpty()); } @Override public void actionPerformed(ActionEvent e) { checkBoxTree.expandAllNodes(); } } private class CollapseAllNodesAction extends AbstractAction { public CollapseAllNodesAction() { super("Collapse all", new ImageIcon(BenchmarkAggregatorFrame.class.getResource("collapseAll.png"))); setEnabled(!plannerBenchmarkResultList.isEmpty()); } @Override public void actionPerformed(ActionEvent e) { checkBoxTree.collapseAllNodes(); } } private class MoveNodeAction extends AbstractAction { private boolean directionUp; public MoveNodeAction(boolean directionUp) { super(directionUp ? "Move up" : "Move down", new ImageIcon( BenchmarkAggregatorFrame.class.getResource(directionUp ? "moveUp.png" : "moveDown.png"))); this.directionUp = directionUp; setEnabled(!plannerBenchmarkResultList.isEmpty()); } @Override public void actionPerformed(ActionEvent e) { if (checkBoxTree.getSelectionPath() != null) { DefaultMutableTreeNode selectedNode = (DefaultMutableTreeNode) checkBoxTree.getSelectionPath() .getLastPathComponent(); DefaultMutableTreeNode parentNode = (DefaultMutableTreeNode) selectedNode.getParent(); if (parentNode != null) { DefaultMutableTreeNode immediateSiblingNode = directionUp ? (DefaultMutableTreeNode) parentNode.getChildBefore(selectedNode) : (DefaultMutableTreeNode) parentNode.getChildAfter(selectedNode); if (immediateSiblingNode != null) { parentNode.insert(immediateSiblingNode, parentNode.getIndex(selectedNode)); ((DefaultTreeModel) checkBoxTree.getModel()).nodeStructureChanged(parentNode); checkBoxTree.setSelectionPath(new TreePath(selectedNode.getPath())); } } } } } private class RenameNodeAction extends AbstractAction { public RenameNodeAction() { super("Rename", new ImageIcon(BenchmarkAggregatorFrame.class.getResource("rename.png"))); setEnabled(!plannerBenchmarkResultList.isEmpty()); } @Override public void actionPerformed(ActionEvent e) { if (checkBoxTree.getSelectionPath() != null) { DefaultMutableTreeNode selectedNode = (DefaultMutableTreeNode) checkBoxTree.getSelectionPath() .getLastPathComponent(); MixedCheckBox mixedCheckBox = (MixedCheckBox) selectedNode.getUserObject(); if (mixedCheckBox.getBenchmarkResult() instanceof PlannerBenchmarkResult || mixedCheckBox.getBenchmarkResult() instanceof SolverBenchmarkResult) { RenameNodeDialog renameNodeDialog = new RenameNodeDialog(selectedNode); renameNodeDialog.pack(); renameNodeDialog.setLocationRelativeTo(BenchmarkAggregatorFrame.this); renameNodeDialog.setVisible(true); } } } } private class SwitchLevelsAction extends AbstractAction { private boolean solverLevelFirst; public SwitchLevelsAction(boolean solverLevelFirst) { super("Switch levels", new ImageIcon(BenchmarkAggregatorFrame.class.getResource("switchTree.png"))); this.solverLevelFirst = solverLevelFirst; setEnabled(!plannerBenchmarkResultList.isEmpty()); } @Override public void actionPerformed(ActionEvent e) { DefaultMutableTreeNode treeRoot = initBenchmarkHierarchy(solverLevelFirst); DefaultTreeModel treeModel = new DefaultTreeModel(treeRoot); checkBoxTree.setModel(treeModel); treeModel.nodeStructureChanged(treeRoot); solverLevelFirst = !solverLevelFirst; checkBoxTree.setSelectedSingleBenchmarkNodes(new HashSet<DefaultMutableTreeNode>()); for (Map.Entry<SingleBenchmarkResult, DefaultMutableTreeNode> entry : resultCheckBoxMapping .entrySet()) { if (((MixedCheckBox) entry.getValue().getUserObject()).getStatus() == MixedCheckBoxStatus.CHECKED) { checkBoxTree.getSelectedSingleBenchmarkNodes().add(entry.getValue()); } } checkBoxTree.updateHierarchyCheckBoxStates(); } } private class RenameNodeDialog extends JDialog { public RenameNodeDialog(final DefaultMutableTreeNode treeNode) { super(BenchmarkAggregatorFrame.this, "Rename node"); final MixedCheckBox mixedCheckBox = (MixedCheckBox) treeNode.getUserObject(); final Object benchmarkResult = mixedCheckBox.getBenchmarkResult(); JPanel mainPanel = new JPanel(new BorderLayout()); String benchmarkResultTextFieldText = null; if (benchmarkResult instanceof SolverBenchmarkResult) { benchmarkResultTextFieldText = solverBenchmarkResultNameMapping.get(benchmarkResult); } final JTextField benchmarkResultNameTextField = new JTextField( benchmarkResultTextFieldText == null ? benchmarkResult.toString() : benchmarkResultTextFieldText, 30); mainPanel.add(benchmarkResultNameTextField, BorderLayout.WEST); AbstractAction renamedAction = new AbstractAction("Rename") { @Override public void actionPerformed(ActionEvent e) { String newBenchmarkResultName = benchmarkResultNameTextField.getText(); if (StringUtils.isEmpty(newBenchmarkResultName)) { JOptionPane.showMessageDialog(BenchmarkAggregatorFrame.this, "New benchmark's name cannot be empty.", "Warning", JOptionPane.WARNING_MESSAGE); } else { if (benchmarkResult instanceof PlannerBenchmarkResult) { ((PlannerBenchmarkResult) benchmarkResult).setName(newBenchmarkResultName); mixedCheckBox.setText(newBenchmarkResultName); ((DefaultTreeModel) checkBoxTree.getModel()).nodeChanged(treeNode); } else if (benchmarkResult instanceof SolverBenchmarkResult) { mixedCheckBox.setText(newBenchmarkResultName + " (" + ((SolverBenchmarkResult) benchmarkResult).getRanking() + ")"); ((DefaultTreeModel) checkBoxTree.getModel()).nodeChanged(treeNode); solverBenchmarkResultNameMapping.put((SolverBenchmarkResult) benchmarkResult, newBenchmarkResultName); } dispose(); } } }; benchmarkResultNameTextField.addActionListener(renamedAction); JButton confirmRenameButton = new JButton(renamedAction); mainPanel.add(confirmRenameButton, BorderLayout.EAST); mainPanel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10)); setContentPane(mainPanel); } } private DefaultMutableTreeNode initBenchmarkHierarchy(boolean solverFirst) { DefaultMutableTreeNode parentNode = new DefaultMutableTreeNode(new MixedCheckBox("Planner benchmarks")); for (PlannerBenchmarkResult plannerBenchmarkResult : plannerBenchmarkResultList) { DefaultMutableTreeNode plannerNode = new DefaultMutableTreeNode( createPlannerBenchmarkCheckBox(plannerBenchmarkResult)); parentNode.add(plannerNode); if (solverFirst) { for (SolverBenchmarkResult solverBenchmarkResult : plannerBenchmarkResult .getSolverBenchmarkResultList()) { DefaultMutableTreeNode solverNode = new DefaultMutableTreeNode( createSolverBenchmarkCheckBox(solverBenchmarkResult)); plannerNode.add(solverNode); for (ProblemBenchmarkResult problemBenchmarkResult : plannerBenchmarkResult .getUnifiedProblemBenchmarkResultList()) { DefaultMutableTreeNode problemNode = new DefaultMutableTreeNode( createProblemBenchmarkCheckBox(problemBenchmarkResult)); solverNode.add(problemNode); initSingleBenchmarkNodes(solverBenchmarkResult, problemBenchmarkResult, problemNode); } } } else { for (ProblemBenchmarkResult problemBenchmarkResult : plannerBenchmarkResult .getUnifiedProblemBenchmarkResultList()) { DefaultMutableTreeNode problemNode = new DefaultMutableTreeNode( createProblemBenchmarkCheckBox(problemBenchmarkResult)); plannerNode.add(problemNode); for (SolverBenchmarkResult solverBenchmarkResult : plannerBenchmarkResult .getSolverBenchmarkResultList()) { DefaultMutableTreeNode solverNode = new DefaultMutableTreeNode( createSolverBenchmarkCheckBox(solverBenchmarkResult)); problemNode.add(solverNode); initSingleBenchmarkNodes(solverBenchmarkResult, problemBenchmarkResult, solverNode); } } } } return parentNode; } private void initSingleBenchmarkNodes(SolverBenchmarkResult solverBenchmarkResult, ProblemBenchmarkResult problemBenchmarkResult, DefaultMutableTreeNode problemNode) { for (SingleBenchmarkResult singleBenchmarkResult : solverBenchmarkResult.getSingleBenchmarkResultList()) { if (singleBenchmarkResult.getProblemBenchmarkResult().equals(problemBenchmarkResult)) { DefaultMutableTreeNode singleBenchmarkNode = resultCheckBoxMapping.get(singleBenchmarkResult); if (singleBenchmarkNode != null) { problemNode.add(singleBenchmarkNode); } else { DefaultMutableTreeNode singleNode = new DefaultMutableTreeNode( createSingleBenchmarkCheckBox(singleBenchmarkResult)); problemNode.add(singleNode); resultCheckBoxMapping.put(singleBenchmarkResult, singleNode); } } } } private MixedCheckBox createPlannerBenchmarkCheckBox(PlannerBenchmarkResult plannerBenchmarkResult) { String plannerBenchmarkDetail = String.format("Average score: %s%n" + "Average problem scale: %d", plannerBenchmarkResult.getAverageScore(), plannerBenchmarkResult.getAverageProblemScale()); return new MixedCheckBox(plannerBenchmarkResult.getName(), plannerBenchmarkDetail, plannerBenchmarkResult); } private MixedCheckBox createSolverBenchmarkCheckBox(SolverBenchmarkResult solverBenchmarkResult) { String solverCheckBoxName = solverBenchmarkResult.getName() + " (" + solverBenchmarkResult.getRanking() + ")"; String solverBenchmarkDetail = String.format( "Average score: %s%n" + "Total score: %s%n" + "Average time spent: %s%n" + "Total winning score difference: %s", solverBenchmarkResult.getAverageScore(), solverBenchmarkResult.getTotalScore(), solverBenchmarkResult.getAverageTimeMillisSpent() == null ? "" : millisecondsSpentNumberFormat.format(solverBenchmarkResult.getAverageTimeMillisSpent()), solverBenchmarkResult.getTotalWinningScoreDifference()); solverBenchmarkResultNameMapping.put(solverBenchmarkResult, solverBenchmarkResult.getName()); return new MixedCheckBox(solverCheckBoxName, solverBenchmarkDetail, solverBenchmarkResult); } private MixedCheckBox createProblemBenchmarkCheckBox(ProblemBenchmarkResult problemBenchmarkResult) { String problemBenchmarkDetail = String.format("Problem scale: %d%n" + "Used memory: %s", problemBenchmarkResult.getProblemScale(), toEmptyStringIfNull(problemBenchmarkResult.getAverageUsedMemoryAfterInputSolution())); return new MixedCheckBox(problemBenchmarkResult.getName(), problemBenchmarkDetail); } private MixedCheckBox createSingleBenchmarkCheckBox(SingleBenchmarkResult singleBenchmarkResult) { String singleCheckBoxName = singleBenchmarkResult.getName() + " (" + singleBenchmarkResult.getRanking() + ")"; String singleBenchmarkDetail = String.format( "Score: %s%n" + "Planning entity count: %d%n" + "Used memory: %s%n" + "Time spent: %s", singleBenchmarkResult.getScore(), singleBenchmarkResult.getEntityCount(), toEmptyStringIfNull(singleBenchmarkResult.getUsedMemoryAfterInputSolution()), millisecondsSpentNumberFormat.format(singleBenchmarkResult.getTimeMillisSpent())); return new MixedCheckBox(singleCheckBoxName, singleBenchmarkDetail, singleBenchmarkResult); } private String toEmptyStringIfNull(Object obj) { return obj == null ? "" : obj.toString(); } private class GenerateReportWorker extends SwingWorker<File, Void> { private final BenchmarkAggregatorFrame parentFrame; private List<SingleBenchmarkResult> singleBenchmarkResultList; public GenerateReportWorker(BenchmarkAggregatorFrame parentFrame, List<SingleBenchmarkResult> singleBenchmarkResultList) { this.parentFrame = parentFrame; this.singleBenchmarkResultList = singleBenchmarkResultList; } @Override protected File doInBackground() { return benchmarkAggregator.aggregate(singleBenchmarkResultList, solverBenchmarkResultNameMapping); } @Override protected void done() { try { File htmlOverviewFile = get(); ReportFinishedDialog dialog = new ReportFinishedDialog(parentFrame, htmlOverviewFile); dialog.pack(); dialog.setLocationRelativeTo(parentFrame); dialog.setVisible(true); } catch (InterruptedException e) { throw new IllegalStateException("The report generation failed.", e); } catch (ExecutionException e) { throw new IllegalStateException("The report generation failed.", e.getCause()); } finally { detailTextArea.setText(null); generateProgressBar.setIndeterminate(false); generateProgressBar.setString(null); generateProgressBar.setStringPainted(false); } } } private class ReportFinishedDialog extends JDialog { private final BenchmarkAggregatorFrame parentFrame; private final File reportFile; private JCheckBox exitCheckBox; public ReportFinishedDialog(BenchmarkAggregatorFrame parentFrame, File reportFile) { super(parentFrame, "Report generation finished"); this.parentFrame = parentFrame; this.reportFile = reportFile; addWindowListener(new WindowAdapter() { @Override public void windowClosing(WindowEvent e) { refresh(); } }); JPanel mainPanel = new JPanel(new BorderLayout(0, 10)); exitCheckBox = new JCheckBox("Exit application", exitApplicationWhenReportFinished); mainPanel.add(exitCheckBox, BorderLayout.NORTH); mainPanel.add(createButtonPanel(), BorderLayout.CENTER); mainPanel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10)); getContentPane().add(mainPanel); } private JPanel createButtonPanel() { final Desktop desktop = Desktop.getDesktop(); JPanel buttonPanel = new JPanel(new GridLayout(1, 3, 10, 10)); AbstractAction openBrowserAction = new AbstractAction("Show in browser") { @Override public void actionPerformed(ActionEvent event) { try { desktop.browse(reportFile.getAbsoluteFile().toURI()); } catch (IOException e) { throw new IllegalStateException( "Failed showing reportFile (" + reportFile + ") in browser.", e); } finishDialog(); } }; openBrowserAction.setEnabled(desktop.isSupported(Desktop.Action.BROWSE)); buttonPanel.add(new JButton(openBrowserAction)); AbstractAction openFileAction = new AbstractAction("Show in files") { @Override public void actionPerformed(ActionEvent event) { try { desktop.open(reportFile.getParentFile()); } catch (IOException e) { throw new IllegalStateException( "Failed showing reportFile (" + reportFile + ") in file explorer.", e); } finishDialog(); } }; openBrowserAction.setEnabled(desktop.isSupported(Desktop.Action.OPEN)); buttonPanel.add(new JButton(openFileAction)); AbstractAction closeAction = new AbstractAction("Ok") { @Override public void actionPerformed(ActionEvent e) { finishDialog(); } }; buttonPanel.add(new JButton(closeAction)); return buttonPanel; } private void finishDialog() { exitApplicationWhenReportFinished = exitCheckBox.isSelected(); if (exitApplicationWhenReportFinished) { parentFrame.dispose(); } else { dispose(); parentFrame.refresh(); } } } private void refresh() { initPlannerBenchmarkResultList(); solverBenchmarkResultNameMapping = new HashMap<SolverBenchmarkResult, String>(); resultCheckBoxMapping = new LinkedHashMap<SingleBenchmarkResult, DefaultMutableTreeNode>(); checkBoxTree.setSelectedSingleBenchmarkNodes(new HashSet<DefaultMutableTreeNode>()); DefaultMutableTreeNode newCheckBoxRootNode = initBenchmarkHierarchy(true); DefaultTreeModel treeModel = new DefaultTreeModel(newCheckBoxRootNode); checkBoxTree.setModel(treeModel); treeModel.nodeStructureChanged(newCheckBoxRootNode); setEnabled(true); } }