/* * Copyright 2016 Laszlo Balazs-Csiki * * This file is part of Pixelitor. Pixelitor is free software: you * can redistribute it and/or modify it under the terms of the GNU * General Public License, version 3 as published by the Free * Software Foundation. * * Pixelitor 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Pixelitor. If not, see <http://www.gnu.org/licenses/>. */ package pixelitor.gui.utils; import pixelitor.ChangeReason; import pixelitor.filters.Filter; import pixelitor.filters.FilterAction; import pixelitor.filters.FilterUtils; import pixelitor.filters.gui.FilterWithGUI; import pixelitor.layers.ImageLayer; import javax.swing.*; import java.awt.BorderLayout; import java.awt.Cursor; import java.awt.EventQueue; import java.awt.FlowLayout; import java.awt.Frame; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; public class PerformanceTestingDialog extends JDialog implements ActionListener, PropertyChangeListener { private final JComboBox<FilterAction> opSelector; private final JProgressBar progressBar; private final JButton startButton; private final JButton stopButton; private final JButton closeButton; private final ImageLayer layer; private TestingTask task; private final JTextField timesField; public PerformanceTestingDialog(Frame parent, ImageLayer layer) { super(parent, "Performance Testing"); this.layer = layer; setLayout(new BorderLayout()); JPanel northPanel = new JPanel(); JPanel centralPanel = new JPanel(); JPanel southPanel = new JPanel(); northPanel.setLayout(new FlowLayout()); opSelector = new JComboBox<>(FilterUtils.getAllFiltersSorted()); opSelector.addActionListener(e -> { Filter op = (Filter) opSelector.getSelectedItem(); if (op instanceof FilterWithGUI) { FilterWithGUI dialogOp = (FilterWithGUI) op; dialogOp.execute(layer); } }); northPanel.add(new JLabel("Select filter: ")); northPanel.add(opSelector); centralPanel.setLayout(new BorderLayout()); JPanel p = new JPanel(); p.setLayout(new FlowLayout(FlowLayout.LEFT)); p.add(new JLabel("How many times: ")); timesField = new IntTextField("100"); timesField.setColumns(7); p.add(timesField); centralPanel.add(p, BorderLayout.NORTH); progressBar = new JProgressBar(0, 100); progressBar.setValue(0); progressBar.setStringPainted(true); centralPanel.add(progressBar, BorderLayout.SOUTH); startButton = new JButton("start"); startButton.addActionListener(this); southPanel.add(startButton); stopButton = new JButton("stop"); stopButton.addActionListener(this); stopButton.setEnabled(false); southPanel.add(stopButton); closeButton = new JButton("close"); closeButton.addActionListener(this); southPanel.add(closeButton); add(northPanel, BorderLayout.NORTH); add(centralPanel, BorderLayout.CENTER); add(southPanel, BorderLayout.SOUTH); pack(); GUIUtils.centerOnScreen(this); setVisible(true); } private void setEnabledWhileRunning() { startButton.setEnabled(false); stopButton.setEnabled(true); closeButton.setEnabled(false); opSelector.setEnabled(false); timesField.setEnabled(false); } private void setEnabledAfterRunning() { startButton.setEnabled(true); stopButton.setEnabled(false); closeButton.setEnabled(true); opSelector.setEnabled(true); timesField.setEnabled(true); } @Override public void actionPerformed(ActionEvent e) { if (e.getSource() == startButton) { int executions = 0; try { executions = Integer.parseInt(timesField.getText().trim()); } catch (NumberFormatException e1) { String message = String.format("\"%s\" is not an integer number.", timesField.getText()); Dialogs.showErrorDialog(this, "Error", message); } if (executions > 0) { setEnabledWhileRunning(); setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); task = new TestingTask(layer, executions); task.addPropertyChangeListener(this); task.execute(); } } else if (e.getSource() == stopButton) { if (task != null) { task.cancel(false); } setEnabledAfterRunning(); } else if (e.getSource() == closeButton) { dispose(); } } @Override public void propertyChange(PropertyChangeEvent evt) { if ("progress".equals(evt.getPropertyName())) { int progress = (Integer) evt.getNewValue(); progressBar.setValue(progress); } } class TestingTask extends SwingWorker<Void, Void> { private final ImageLayer layer; private int executions = 0; private Filter op; private long totalTime; private TestingTask(ImageLayer layer, int testExecutions) { this.layer = layer; this.executions = testExecutions; } @Override public Void doInBackground() { //Initialize progress property. int progress = 0; setProgress(progress); op = (Filter) opSelector.getSelectedItem(); long startTime = System.nanoTime(); long shortestTime = Long.MAX_VALUE; for (int i = 0; i < executions; i++) { long individualStartTime = System.nanoTime(); op.execute(layer, ChangeReason.TEST_NO_HISTORY_NO_PREVIEW); long individualTotalTime = (System.nanoTime() - individualStartTime) / 1000000; if (individualTotalTime < shortestTime) { shortestTime = individualTotalTime; } progress = 100 * (i + 1) / executions; setProgress(progress); if (isCancelled()) { totalTime = (System.nanoTime() - startTime) / 1000000; String results = getReport(op.getName(), (i + 1), totalTime, shortestTime); showResults(results); return null; } } totalTime = (System.nanoTime() - startTime) / 1000000; String results = getReport(op.getName(), executions, totalTime, shortestTime); showResults(results); return null; } private void showResults(String results) { EventQueue.invokeLater(() -> JOptionPane.showMessageDialog(PerformanceTestingDialog.this, results, "Performance Testing Results", JOptionPane.INFORMATION_MESSAGE)); } private String getReport(String opName, int executions, long totalTime, long shortestTime) { return ("Executing \"" + opName + "\" " + executions + " times took " + totalTime + " ms, average time = " + totalTime / executions + " ms, shortest time = " + shortestTime + "ms."); } /* * Executed in event dispatching thread */ @Override public void done() { // Toolkit.getDefaultToolkit().beep(); setCursor(null); //turn off the wait cursor setEnabledAfterRunning(); } } }