Tue, 28 Jul 2020 14:05:04 +0200
DocumentHandlerTest tests if modified state is reset
/* * Copyright 2013 Mike Becker. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ package de.uapcore.sudoku; import javax.swing.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.io.File; import java.io.IOException; /** * Handles all user issued actions in the application. */ public final class ActionHandler implements ActionListener { public static final String SAVE = "save"; public static final String CHECK = "check"; public static final String SOLVE = "solve"; public static final String NEW = "new"; public static final String OPEN = "open"; public static final String SAVE_AS = "save as"; public static final String QUIT = "quit"; public static final String ABOUT = "about"; private final Field field; private final Solver solver; private final DocumentHandler doc; /** * Constructs a new action handler instance. * * @param f a reference to the playing field */ public ActionHandler(Field f) { field = f; solver = new Solver(); doc = new DocumentHandler(); } /** * Prompts the user for a file name. * <p> * If the user chooses an existing file, they are asked whether the file should be overwritten. * * @return true if the user approves a chosen file name */ private boolean chooseSaveFilename() { JFileChooser fc = new JFileChooser("."); fc.setMultiSelectionEnabled(false); if (fc.showSaveDialog(field) == JFileChooser.APPROVE_OPTION) { File f = fc.getSelectedFile(); if (f.exists()) { int result = JOptionPane.showConfirmDialog(field, "Bereits existierende Datei überschreiben?", "Sudoku", JOptionPane.YES_NO_OPTION); if (result == JOptionPane.YES_OPTION) { doc.setFilename(f.getAbsolutePath()); return true; } else { return false; } } else { doc.setFilename(f.getAbsolutePath()); return true; } } else { return false; } } /** * Prompts the user for a file to open and, if approved, loads that file. */ private void open() { JFileChooser fc = new JFileChooser("."); fc.setMultiSelectionEnabled(false); if (fc.showOpenDialog(field) == JFileChooser.APPROVE_OPTION) { File f = fc.getSelectedFile(); doc.setFilename(f.getAbsolutePath()); try { doc.load(field); } catch (IOException e) { JOptionPane.showMessageDialog(field, "Datei konnte nicht geladen werden: " + e.getMessage(), "Sudoku", JOptionPane.ERROR_MESSAGE); } } } /** * Attempts to save the Sudoku field to a file. * <p> * If necessary, the user is prompted for a file name. * <p> * The field must be solvable, otherwise it cannot be saved. * * @param rename true if the user shall always be prompted, even if a file name is already known * @return true if the user approves the chosen file name */ private boolean save(boolean rename) { if (!doc.isFilenameSet() || rename) { if (!chooseSaveFilename()) { return false; } } if (solver.check(field)) { field.setAllCellsModified(false); try { doc.save(field); } catch (IOException e) { JOptionPane.showMessageDialog(field, "Datei konnte nicht gespeichert werden: " + e.getMessage(), "Sudoku", JOptionPane.ERROR_MESSAGE); } return true; } else { JOptionPane.showMessageDialog(field, "Das Feld kann mit Fehlern nicht gespeichert werden!", "Sudoku", JOptionPane.ERROR_MESSAGE); return false; } } /** * Checks the Sudoku field and displays the result as a dialog box. */ private void check() { if (solver.check(field)) { JOptionPane.showMessageDialog(field, "Überprüfung erfolgreich!", "Sudoku", JOptionPane.INFORMATION_MESSAGE); } else { JOptionPane.showMessageDialog(field, "Das Feld enthält Fehler!", "Sudoku", JOptionPane.WARNING_MESSAGE); } } /** * Solves the field or displays an error dialog if the field is not solvable. */ private void solve() { if (!solver.check(field) || !solver.solve(field)) { JOptionPane.showMessageDialog(field, "Das Feld ist nicht lösbar!", "Sudoku", JOptionPane.WARNING_MESSAGE); } } /** * Checks whether there are unsaved changes and asks the user to save the field. * * @return true if there are no unsaved changes or the user actively decides to continue - false, otherwise */ private boolean saveUnsaved() { boolean proceed = false; if (field.isAnyCellModified()) { int result = JOptionPane.showConfirmDialog(field, "Das Feld ist ungespeichert - jetzt speichern?", "Sudoku", JOptionPane.YES_NO_CANCEL_OPTION); if (result == JOptionPane.YES_OPTION) { if (save(false)) { proceed = true; } } else if (result == JOptionPane.NO_OPTION) { proceed = true; } } else { proceed = true; } return proceed; } @Override public void actionPerformed(ActionEvent e) { switch (e.getActionCommand()) { case NEW: if (saveUnsaved()) { doc.clearFilename(); field.clear(); } break; case OPEN: open(); break; case SAVE: save(false); break; case SAVE_AS: save(true); break; case CHECK: check(); break; case SOLVE: solve(); break; case QUIT: if (saveUnsaved()) { System.exit(0); } break; case ABOUT: JOptionPane.showMessageDialog(field, "Sudoku - Copyright (c) 2013 Mike Becker\nwww.uap-core.de" + "\nPublished under the BSD License", "Sudoku", JOptionPane.INFORMATION_MESSAGE); break; default: throw new UnsupportedOperationException( "unknown action: " + e.getActionCommand()); } } }