/*
* Copyright 2010 Red Hat, Inc. and/or its affiliates.
*
* 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.examples.common.swingui;
import java.awt.BorderLayout;
import java.awt.CardLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutionException;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.BorderFactory;
import javax.swing.BoxLayout;
import javax.swing.GroupLayout;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.JToggleButton;
import javax.swing.SwingConstants;
import javax.swing.SwingWorker;
import javax.swing.filechooser.FileFilter;
import org.apache.commons.io.FilenameUtils;
import org.optaplanner.core.api.domain.solution.PlanningSolution;
import org.optaplanner.core.api.score.FeasibilityScore;
import org.optaplanner.core.api.score.Score;
import org.optaplanner.examples.common.business.SolutionBusiness;
import org.optaplanner.examples.common.persistence.AbstractSolutionImporter;
import org.optaplanner.swing.impl.SwingUtils;
import org.optaplanner.swing.impl.TangoColorFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* @param <Solution_> the solution type, the class with the {@link PlanningSolution} annotation
*/
public class SolverAndPersistenceFrame<Solution_> extends JFrame {
protected final transient Logger logger = LoggerFactory.getLogger(getClass());
public static final ImageIcon OPTA_PLANNER_ICON = new ImageIcon(
SolverAndPersistenceFrame.class.getResource("optaPlannerIcon.png"));
private final SolutionBusiness<Solution_> solutionBusiness;
private final ImageIcon indictmentHeatMapTrueIcon;
private final ImageIcon indictmentHeatMapFalseIcon;
private final ImageIcon refreshScreenDuringSolvingTrueIcon;
private final ImageIcon refreshScreenDuringSolvingFalseIcon;
private SolutionPanel<Solution_> solutionPanel;
private ConstraintMatchesDialog constraintMatchesDialog;
private JPanel quickOpenUnsolvedPanel;
private List<Action> quickOpenUnsolvedActionList;
private JPanel quickOpenSolvedPanel;
private List<Action> quickOpenSolvedActionList;
private Action openAction;
private Action saveAction;
private Action importAction;
private Action exportAction;
private JToggleButton refreshScreenDuringSolvingToggleButton;
private JToggleButton indictmentHeatMapToggleButton;
private Action solveAction;
private JButton solveButton;
private Action terminateSolvingEarlyAction;
private JButton terminateSolvingEarlyButton;
private JPanel middlePanel;
private JProgressBar progressBar;
private JTextField scoreField;
private ShowConstraintMatchesDialogAction showConstraintMatchesDialogAction;
public SolverAndPersistenceFrame(SolutionBusiness<Solution_> solutionBusiness,
SolutionPanel<Solution_> solutionPanel) {
super(solutionBusiness.getAppName() + " OptaPlanner example");
this.solutionBusiness = solutionBusiness;
this.solutionPanel = solutionPanel;
setIconImage(OPTA_PLANNER_ICON.getImage());
solutionPanel.setSolutionBusiness(solutionBusiness);
solutionPanel.setSolverAndPersistenceFrame(this);
indictmentHeatMapTrueIcon = new ImageIcon(getClass().getResource("indictmentHeatMapTrueIcon.png"));
indictmentHeatMapFalseIcon = new ImageIcon(getClass().getResource("indictmentHeatMapFalseIcon.png"));
refreshScreenDuringSolvingTrueIcon = new ImageIcon(getClass().getResource("refreshScreenDuringSolvingTrueIcon.png"));
refreshScreenDuringSolvingFalseIcon = new ImageIcon(getClass().getResource("refreshScreenDuringSolvingFalseIcon.png"));
registerListeners();
constraintMatchesDialog = new ConstraintMatchesDialog(this, solutionBusiness);
}
private void registerListeners() {
solutionBusiness.registerForBestSolutionChanges(this);
addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
// This async, so it doesn't stop the solving immediately
solutionBusiness.terminateSolvingEarly();
}
});
}
public void bestSolutionChanged() {
Solution_ solution = solutionBusiness.getSolution();
Score score = solutionBusiness.getScore();
if (refreshScreenDuringSolvingToggleButton.isSelected()) {
solutionPanel.updatePanel(solution);
validate(); // TODO remove me?
}
refreshScoreField(score);
}
public void init(Component centerForComponent) {
setContentPane(createContentPane());
pack();
setLocationRelativeTo(centerForComponent);
}
private JComponent createContentPane() {
JComponent quickOpenPanel = createQuickOpenPanel();
JPanel mainPanel = new JPanel(new BorderLayout());
mainPanel.add(createToolBar(), BorderLayout.NORTH);
mainPanel.add(createMiddlePanel(), BorderLayout.CENTER);
mainPanel.add(createScorePanel(), BorderLayout.SOUTH);
JSplitPane splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, quickOpenPanel, mainPanel);
splitPane.setOneTouchExpandable(true);
splitPane.setResizeWeight(0.2);
return splitPane;
}
private JComponent createQuickOpenPanel() {
JPanel quickOpenPanel = new JPanel(new BorderLayout());
JLabel quickOpenLabel = new JLabel("Quick open");
quickOpenLabel.setBorder(BorderFactory.createEmptyBorder(2, 2, 2, 2));
quickOpenPanel.add(quickOpenLabel, BorderLayout.NORTH);
JSplitPane splitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT,
createQuickOpenUnsolvedPanel(), createQuickOpenSolvedPanel());
splitPane.setResizeWeight(0.8);
splitPane.setBorder(null);
quickOpenPanel.add(splitPane, BorderLayout.CENTER);
return quickOpenPanel;
}
private JComponent createQuickOpenUnsolvedPanel() {
quickOpenUnsolvedPanel = new JPanel();
quickOpenUnsolvedActionList = new ArrayList<>();
List<File> unsolvedFileList = solutionBusiness.getUnsolvedFileList();
return createQuickOpenPanel(quickOpenUnsolvedPanel, "Unsolved dataset", quickOpenUnsolvedActionList,
unsolvedFileList);
}
private JComponent createQuickOpenSolvedPanel() {
quickOpenSolvedPanel = new JPanel();
quickOpenSolvedActionList = new ArrayList<>();
List<File> solvedFileList = solutionBusiness.getSolvedFileList();
return createQuickOpenPanel(quickOpenSolvedPanel, "Solved dataset", quickOpenSolvedActionList,
solvedFileList);
}
private JComponent createQuickOpenPanel(JPanel panel, String title, List<Action> quickOpenActionList, List<File> fileList) {
panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
refreshQuickOpenPanel(panel, quickOpenActionList, fileList);
JScrollPane scrollPane = new JScrollPane(panel);
scrollPane.getVerticalScrollBar().setUnitIncrement(25);
scrollPane.setMinimumSize(new Dimension(100, 80));
// Size fits into screen resolution 1024*768
scrollPane.setPreferredSize(new Dimension(180, 200));
JPanel titlePanel = new JPanel(new BorderLayout());
titlePanel.add(scrollPane, BorderLayout.CENTER);
titlePanel.setBorder(BorderFactory.createCompoundBorder(
BorderFactory.createEmptyBorder(2, 2, 2, 2), BorderFactory.createTitledBorder(title)));
return titlePanel;
}
private void refreshQuickOpenPanel(JPanel panel, List<Action> quickOpenActionList, List<File> fileList) {
panel.removeAll();
quickOpenActionList.clear();
if (fileList.isEmpty()) {
JLabel noneLabel = new JLabel("None");
noneLabel.setBorder(BorderFactory.createEmptyBorder(2, 2, 2, 2));
panel.add(noneLabel);
} else {
for (File file : fileList) {
Action quickOpenAction = new QuickOpenAction(file);
quickOpenActionList.add(quickOpenAction);
JButton quickOpenButton = SwingUtils.makeSmallButton(new JButton(quickOpenAction));
quickOpenButton.setHorizontalAlignment(SwingConstants.LEFT);
panel.add(quickOpenButton);
}
}
}
private class QuickOpenAction extends AbstractAction {
private File file;
public QuickOpenAction(File file) {
super(file.getName().replaceAll("\\.xml$", ""));
this.file = file;
}
@Override
public void actionPerformed(ActionEvent e) {
setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
try {
solutionBusiness.openSolution(file);
setSolutionLoaded();
} finally {
setCursor(Cursor.getDefaultCursor());
}
}
}
private JComponent createToolBar() {
// JToolBar looks ugly in Nimbus LookAndFeel
JPanel toolBar = new JPanel();
GroupLayout toolBarLayout = new GroupLayout(toolBar);
toolBar.setLayout(toolBarLayout);
importAction = new ImportAction();
importAction.setEnabled(solutionBusiness.hasImporter());
JButton importButton = new JButton(importAction);
openAction = new OpenAction();
openAction.setEnabled(true);
JButton openButton = new JButton(openAction);
saveAction = new SaveAction();
saveAction.setEnabled(false);
JButton saveButton = new JButton(saveAction);
exportAction = new ExportAction();
exportAction.setEnabled(false);
JButton exportButton = new JButton(exportAction);
progressBar = new JProgressBar(0, 100);
JPanel solvePanel = new JPanel(new CardLayout());
solveAction = new SolveAction();
solveAction.setEnabled(false);
solveButton = new JButton(solveAction);
terminateSolvingEarlyAction = new TerminateSolvingEarlyAction();
terminateSolvingEarlyAction.setEnabled(false);
terminateSolvingEarlyButton = new JButton(terminateSolvingEarlyAction);
terminateSolvingEarlyButton.setVisible(false);
solvePanel.add(solveButton, "solveAction");
solvePanel.add(terminateSolvingEarlyButton, "terminateSolvingEarlyAction");
solveButton.setMinimumSize(terminateSolvingEarlyButton.getMinimumSize());
solveButton.setPreferredSize(terminateSolvingEarlyButton.getPreferredSize());
toolBarLayout.setHorizontalGroup(toolBarLayout.createSequentialGroup()
.addComponent(importButton)
.addComponent(openButton)
.addComponent(saveButton)
.addComponent(exportButton)
.addGap(10)
.addComponent(solvePanel, GroupLayout.PREFERRED_SIZE, GroupLayout.PREFERRED_SIZE, GroupLayout.PREFERRED_SIZE)
.addComponent(progressBar, 20, GroupLayout.PREFERRED_SIZE, GroupLayout.PREFERRED_SIZE));
toolBarLayout.setVerticalGroup(toolBarLayout.createParallelGroup(GroupLayout.Alignment.CENTER)
.addComponent(importButton)
.addComponent(openButton)
.addComponent(saveButton)
.addComponent(exportButton)
.addComponent(solvePanel)
.addComponent(progressBar));
return toolBar;
}
private class SolveAction extends AbstractAction {
public SolveAction() {
super("Solve", new ImageIcon(SolverAndPersistenceFrame.class.getResource("solveAction.png")));
}
@Override
public void actionPerformed(ActionEvent e) {
setSolvingState(true);
Solution_ planningProblem = solutionBusiness.getSolution();
new SolveWorker(planningProblem).execute();
}
}
protected class SolveWorker extends SwingWorker<Solution_, Void> {
protected final Solution_ planningProblem;
public SolveWorker(Solution_ planningProblem) {
this.planningProblem = planningProblem;
}
@Override
protected Solution_ doInBackground() throws Exception {
return solutionBusiness.solve(planningProblem);
}
@Override
protected void done() {
try {
Solution_ bestSolution = get();
solutionBusiness.setSolution(bestSolution);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
throw new IllegalStateException("Solving was interrupted.", e);
} catch (ExecutionException e) {
throw new IllegalStateException("Solving failed.", e.getCause());
} finally {
setSolvingState(false);
resetScreen();
}
}
}
private class TerminateSolvingEarlyAction extends AbstractAction {
public TerminateSolvingEarlyAction() {
super("Terminate solving early",
new ImageIcon(SolverAndPersistenceFrame.class.getResource("terminateSolvingEarlyAction.png")));
}
@Override
public void actionPerformed(ActionEvent e) {
terminateSolvingEarlyAction.setEnabled(false);
progressBar.setString("Terminating...");
// This async, so it doesn't stop the solving immediately
solutionBusiness.terminateSolvingEarly();
}
}
private class OpenAction extends AbstractAction {
private static final String NAME = "Open...";
private JFileChooser fileChooser;
public OpenAction() {
super(NAME, new ImageIcon(SolverAndPersistenceFrame.class.getResource("openAction.png")));
fileChooser = new JFileChooser(solutionBusiness.getSolvedDataDir());
fileChooser.setFileFilter(new FileFilter() {
@Override
public boolean accept(File file) {
return file.isDirectory() || file.getName().endsWith(".xml");
}
@Override
public String getDescription() {
return "Solution XStream XML files";
}
});
fileChooser.setDialogTitle(NAME);
}
@Override
public void actionPerformed(ActionEvent e) {
int approved = fileChooser.showOpenDialog(SolverAndPersistenceFrame.this);
if (approved == JFileChooser.APPROVE_OPTION) {
setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
try {
solutionBusiness.openSolution(fileChooser.getSelectedFile());
setSolutionLoaded();
} finally {
setCursor(Cursor.getDefaultCursor());
}
}
}
}
private class SaveAction extends AbstractAction {
private static final String NAME = "Save as...";
private JFileChooser fileChooser;
public SaveAction() {
super(NAME, new ImageIcon(SolverAndPersistenceFrame.class.getResource("saveAction.png")));
fileChooser = new JFileChooser(solutionBusiness.getSolvedDataDir());
fileChooser.setFileFilter(new FileFilter() {
@Override
public boolean accept(File file) {
return file.isDirectory() || file.getName().endsWith(".xml");
}
@Override
public String getDescription() {
return "Solution XStream XML files";
}
});
fileChooser.setDialogTitle(NAME);
}
@Override
public void actionPerformed(ActionEvent e) {
fileChooser.setSelectedFile(new File(solutionBusiness.getSolvedDataDir(),
FilenameUtils.getBaseName(solutionBusiness.getSolutionFileName()) + ".xml"));
int approved = fileChooser.showSaveDialog(SolverAndPersistenceFrame.this);
if (approved == JFileChooser.APPROVE_OPTION) {
setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
try {
solutionBusiness.saveSolution(fileChooser.getSelectedFile());
} finally {
setCursor(Cursor.getDefaultCursor());
}
refreshQuickOpenPanel(quickOpenUnsolvedPanel, quickOpenUnsolvedActionList,
solutionBusiness.getUnsolvedFileList());
refreshQuickOpenPanel(quickOpenSolvedPanel, quickOpenSolvedActionList,
solutionBusiness.getSolvedFileList());
SolverAndPersistenceFrame.this.validate();
}
}
}
private class ImportAction extends AbstractAction {
private static final String NAME = "Import...";
private JFileChooser fileChooser;
public ImportAction() {
super(NAME, new ImageIcon(SolverAndPersistenceFrame.class.getResource("importAction.png")));
if (!solutionBusiness.hasImporter()) {
fileChooser = null;
return;
}
fileChooser = new JFileChooser(solutionBusiness.getImportDataDir());
boolean firstFilter = true;
for (final AbstractSolutionImporter importer : solutionBusiness.getImporters()) {
FileFilter filter;
if (importer.isInputFileDirectory()) {
filter = new FileFilter() {
@Override
public boolean accept(File file) {
return file.isDirectory();
}
@Override
public String getDescription() {
return "Import directory";
}
};
fileChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
} else {
filter = new FileFilter() {
@Override
public boolean accept(File file) {
return file.isDirectory() || importer.acceptInputFile(file);
}
@Override
public String getDescription() {
return "Import files (*." + importer.getInputFileSuffix() + ")";
}
};
}
fileChooser.addChoosableFileFilter(filter);
if (firstFilter) {
fileChooser.setFileFilter(filter);
firstFilter = false;
}
}
fileChooser.setDialogTitle(NAME);
}
@Override
public void actionPerformed(ActionEvent e) {
int approved = fileChooser.showOpenDialog(SolverAndPersistenceFrame.this);
if (approved == JFileChooser.APPROVE_OPTION) {
File file = fileChooser.getSelectedFile();
setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
try {
solutionBusiness.importSolution(file);
setSolutionLoaded();
} finally {
setCursor(Cursor.getDefaultCursor());
}
}
}
}
private class ExportAction extends AbstractAction {
private static final String NAME = "Export as...";
private final JFileChooser fileChooser;
public ExportAction() {
super(NAME, new ImageIcon(SolverAndPersistenceFrame.class.getResource("exportAction.png")));
if (!solutionBusiness.hasExporter()) {
fileChooser = null;
return;
}
fileChooser = new JFileChooser(solutionBusiness.getExportDataDir());
fileChooser.setFileFilter(new FileFilter() {
@Override
public boolean accept(File file) {
return file.isDirectory() || file.getName().endsWith("." + solutionBusiness.getExportFileSuffix());
}
@Override
public String getDescription() {
return "Export files (*." + solutionBusiness.getExportFileSuffix() + ")";
}
});
fileChooser.setDialogTitle(NAME);
}
@Override
public void actionPerformed(ActionEvent e) {
fileChooser.setSelectedFile(new File(solutionBusiness.getExportDataDir(),
FilenameUtils.getBaseName(solutionBusiness.getSolutionFileName())
+ "." + solutionBusiness.getExportFileSuffix()
));
int approved = fileChooser.showSaveDialog(SolverAndPersistenceFrame.this);
if (approved == JFileChooser.APPROVE_OPTION) {
setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
try {
solutionBusiness.exportSolution(fileChooser.getSelectedFile());
} finally {
setCursor(Cursor.getDefaultCursor());
}
}
}
}
private JPanel createMiddlePanel() {
middlePanel = new JPanel(new CardLayout());
JPanel usageExplanationPanel = new JPanel(new BorderLayout(5, 5));
ImageIcon usageExplanationIcon = new ImageIcon(getClass().getResource(solutionPanel.getUsageExplanationPath()));
JLabel usageExplanationLabel = new JLabel(usageExplanationIcon);
// Allow splitPane divider to be moved to the right
usageExplanationLabel.setMinimumSize(new Dimension(100, 100));
usageExplanationPanel.add(usageExplanationLabel, BorderLayout.CENTER);
JPanel descriptionPanel = new JPanel(new BorderLayout(2, 2));
descriptionPanel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
descriptionPanel.add(new JLabel("Example description"), BorderLayout.NORTH);
JTextArea descriptionTextArea = new JTextArea(8, 70);
descriptionTextArea.setEditable(false);
descriptionTextArea.setText(solutionBusiness.getAppDescription());
descriptionPanel.add(new JScrollPane(descriptionTextArea,
JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED), BorderLayout.CENTER);
usageExplanationPanel.add(descriptionPanel, BorderLayout.SOUTH);
middlePanel.add(usageExplanationPanel, "usageExplanationPanel");
JComponent wrappedSolutionPanel;
if (solutionPanel.isWrapInScrollPane()) {
wrappedSolutionPanel = new JScrollPane(solutionPanel);
} else {
wrappedSolutionPanel = solutionPanel;
}
middlePanel.add(wrappedSolutionPanel, "solutionPanel");
return middlePanel;
}
private JPanel createScorePanel() {
JPanel scorePanel = new JPanel(new BorderLayout(5, 0));
JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.LEFT, 0, 0));
showConstraintMatchesDialogAction = new ShowConstraintMatchesDialogAction();
showConstraintMatchesDialogAction.setEnabled(false);
buttonPanel.add(new JButton(showConstraintMatchesDialogAction));
indictmentHeatMapToggleButton = new JToggleButton(
solutionPanel.isUseIndictmentColor() ? indictmentHeatMapTrueIcon : indictmentHeatMapFalseIcon,
solutionPanel.isUseIndictmentColor());
indictmentHeatMapToggleButton.setEnabled(false);
indictmentHeatMapToggleButton.setToolTipText("Show indictment heat map");
indictmentHeatMapToggleButton.addActionListener(e -> {
boolean selected = indictmentHeatMapToggleButton.isSelected();
indictmentHeatMapToggleButton.setIcon(selected ?
indictmentHeatMapTrueIcon : indictmentHeatMapFalseIcon);
solutionPanel.setUseIndictmentColor(selected);
resetScreen();
});
buttonPanel.add(indictmentHeatMapToggleButton);
scorePanel.add(buttonPanel, BorderLayout.WEST);
scoreField = new JTextField("Score:");
scoreField.setEditable(false);
scoreField.setForeground(Color.BLACK);
scoreField.setBorder(BorderFactory.createLoweredBevelBorder());
scorePanel.add(scoreField, BorderLayout.CENTER);
refreshScreenDuringSolvingToggleButton = new JToggleButton(refreshScreenDuringSolvingTrueIcon, true);
refreshScreenDuringSolvingToggleButton.setToolTipText("Refresh screen during solving");
refreshScreenDuringSolvingToggleButton.addActionListener(e -> {
refreshScreenDuringSolvingToggleButton.setIcon(refreshScreenDuringSolvingToggleButton.isSelected() ?
refreshScreenDuringSolvingTrueIcon : refreshScreenDuringSolvingFalseIcon);
});
scorePanel.add(refreshScreenDuringSolvingToggleButton, BorderLayout.EAST);
return scorePanel;
}
private class ShowConstraintMatchesDialogAction extends AbstractAction {
public ShowConstraintMatchesDialogAction() {
super("Constraint matches", new ImageIcon(SolverAndPersistenceFrame.class.getResource("showConstraintMatchesDialogAction.png")));
}
@Override
public void actionPerformed(ActionEvent e) {
constraintMatchesDialog.resetContentPanel();
constraintMatchesDialog.setVisible(true);
}
}
private void setSolutionLoaded() {
setTitle(solutionBusiness.getAppName() + " - " + solutionBusiness.getSolutionFileName());
((CardLayout) middlePanel.getLayout()).show(middlePanel, "solutionPanel");
setSolvingState(false);
resetScreen();
}
private void setSolvingState(boolean solving) {
for (Action action : quickOpenUnsolvedActionList) {
action.setEnabled(!solving);
}
for (Action action : quickOpenSolvedActionList) {
action.setEnabled(!solving);
}
importAction.setEnabled(!solving && solutionBusiness.hasImporter());
openAction.setEnabled(!solving);
saveAction.setEnabled(!solving);
exportAction.setEnabled(!solving && solutionBusiness.hasExporter());
solveAction.setEnabled(!solving);
solveButton.setVisible(!solving);
terminateSolvingEarlyAction.setEnabled(solving);
terminateSolvingEarlyButton.setVisible(solving);
if (solving) {
terminateSolvingEarlyButton.requestFocus();
} else {
solveButton.requestFocus();
}
solutionPanel.setEnabled(!solving);
progressBar.setIndeterminate(solving);
progressBar.setStringPainted(solving);
progressBar.setString(solving ? "Solving..." : null);
indictmentHeatMapToggleButton.setEnabled(solutionPanel.isIndictmentHeatMapEnabled() && !solving);
showConstraintMatchesDialogAction.setEnabled(!solving);
}
public void resetScreen() {
Solution_ solution = solutionBusiness.getSolution();
Score score = solutionBusiness.getScore();
solutionPanel.resetPanel(solution);
validate();
refreshScoreField(score);
}
public void refreshScoreField(Score score) {
scoreField.setForeground(determineScoreFieldForeground(score));
scoreField.setText("Latest best score: " + score);
}
private Color determineScoreFieldForeground(Score<?> score) {
if (!score.isSolutionInitialized()) {
return TangoColorFactory.SCARLET_3;
} else if (!(score instanceof FeasibilityScore)) {
return Color.BLACK;
} else {
FeasibilityScore<?> feasibilityScore = (FeasibilityScore<?>) score;
return feasibilityScore.isFeasible() ? TangoColorFactory.CHAMELEON_3 : TangoColorFactory.ORANGE_3;
}
}
}