Mon, 27 Jul 2020 10:56:17 +0200
fixes some code inspection issues
1 /*
2 * Copyright 2013 Mike Becker. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
6 *
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 *
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
15 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
18 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
19 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
20 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
21 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
22 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
23 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
24 * POSSIBILITY OF SUCH DAMAGE.
25 */
27 package de.uapcore.sudoku;
29 import javax.swing.*;
30 import java.awt.event.ActionEvent;
31 import java.awt.event.ActionListener;
32 import java.io.File;
33 import java.io.IOException;
35 /**
36 * Handles all user issued actions in the application.
37 */
38 public final class ActionHandler implements ActionListener {
40 public static final String SAVE = "save";
41 public static final String CHECK = "check";
42 public static final String SOLVE = "solve";
44 public static final String NEW = "new";
45 public static final String OPEN = "open";
46 public static final String SAVE_AS = "save as";
47 public static final String QUIT = "quit";
48 public static final String ABOUT = "about";
50 private final Field field;
51 private final Solver solver;
52 private final DocumentHandler doc;
54 /**
55 * Constructs a new action handler instance.
56 *
57 * @param f a reference to the playing field
58 */
59 public ActionHandler(Field f) {
60 field = f;
61 solver = new Solver();
62 doc = new DocumentHandler();
63 }
65 /**
66 * Prompts the user for a file name.
67 * <p>
68 * If the user chooses an existing file, they are asked whether the file should be overwritten.
69 *
70 * @return true if the user approves a chosen file name
71 */
72 private boolean chooseSaveFilename() {
73 JFileChooser fc = new JFileChooser(".");
74 fc.setMultiSelectionEnabled(false);
75 if (fc.showSaveDialog(field) == JFileChooser.APPROVE_OPTION) {
76 File f = fc.getSelectedFile();
77 if (f.exists()) {
78 int result = JOptionPane.showConfirmDialog(field,
79 "Bereits existierende Datei überschreiben?", "Sudoku",
80 JOptionPane.YES_NO_OPTION);
81 if (result == JOptionPane.YES_OPTION) {
82 doc.setFilename(f.getAbsolutePath());
83 return true;
84 } else {
85 return false;
86 }
87 } else {
88 doc.setFilename(f.getAbsolutePath());
89 return true;
90 }
91 } else {
92 return false;
93 }
94 }
96 /**
97 * Prompts the user for a file to open and, if approved, loads that file.
98 */
99 private void open() {
100 JFileChooser fc = new JFileChooser(".");
101 fc.setMultiSelectionEnabled(false);
102 if (fc.showOpenDialog(field) == JFileChooser.APPROVE_OPTION) {
103 File f = fc.getSelectedFile();
104 doc.setFilename(f.getAbsolutePath());
105 try {
106 doc.load(field);
107 } catch (IOException e) {
108 JOptionPane.showMessageDialog(field,
109 "Datei konnte nicht geladen werden: " + e.getMessage(),
110 "Sudoku", JOptionPane.ERROR_MESSAGE);
111 }
112 }
113 }
115 /**
116 * Attempts to save the Sudoku field to a file.
117 * <p>
118 * If necessary, the user is prompted for a file name.
119 * <p>
120 * The field must be solvable, otherwise it cannot be saved.
121 *
122 * @param rename true if the user shall always be prompted, even if a file name is already known
123 * @return true if the user approves the chosen file name
124 */
125 private boolean save(boolean rename) {
126 if (!doc.isFilenameSet() || rename) {
127 if (!chooseSaveFilename()) {
128 return false;
129 }
130 }
131 if (solver.check(field)) {
132 field.setAllCellsModified(false);
133 try {
134 doc.save(field);
135 } catch (IOException e) {
136 JOptionPane.showMessageDialog(field,
137 "Datei konnte nicht gespeichert werden: " + e.getMessage(),
138 "Sudoku", JOptionPane.ERROR_MESSAGE);
139 }
140 return true;
141 } else {
142 JOptionPane.showMessageDialog(field,
143 "Das Feld kann mit Fehlern nicht gespeichert werden!",
144 "Sudoku", JOptionPane.ERROR_MESSAGE);
145 return false;
146 }
147 }
149 /**
150 * Checks the Sudoku field and displays the result as a dialog box.
151 */
152 private void check() {
153 if (solver.check(field)) {
154 JOptionPane.showMessageDialog(field, "Überprüfung erfolgreich!",
155 "Sudoku", JOptionPane.INFORMATION_MESSAGE);
156 } else {
157 JOptionPane.showMessageDialog(field, "Das Feld enthält Fehler!",
158 "Sudoku", JOptionPane.WARNING_MESSAGE);
159 }
160 }
162 /**
163 * Solves the field or displays an error dialog if the field is not solvable.
164 */
165 private void solve() {
166 if (!solver.check(field) || !solver.solve(field)) {
167 JOptionPane.showMessageDialog(field, "Das Feld ist nicht lösbar!",
168 "Sudoku", JOptionPane.WARNING_MESSAGE);
169 }
170 }
172 /**
173 * Checks whether there are unsaved changes and asks the user to save the field.
174 *
175 * @return true if there are no unsaved changes or the user actively decides to continue - false, otherwise
176 */
177 private boolean saveUnsaved() {
178 boolean proceed = false;
179 if (field.isAnyCellModified()) {
180 int result = JOptionPane.showConfirmDialog(field,
181 "Das Feld ist ungespeichert - jetzt speichern?",
182 "Sudoku", JOptionPane.YES_NO_CANCEL_OPTION);
183 if (result == JOptionPane.YES_OPTION) {
184 if (save(false)) {
185 proceed = true;
186 }
187 } else if (result == JOptionPane.NO_OPTION) {
188 proceed = true;
189 }
190 } else {
191 proceed = true;
192 }
194 return proceed;
195 }
197 @Override
198 public void actionPerformed(ActionEvent e) {
199 switch (e.getActionCommand()) {
200 case NEW:
201 if (saveUnsaved()) {
202 doc.clearFilename();
203 field.clear();
204 }
205 break;
206 case OPEN:
207 open();
208 break;
209 case SAVE:
210 save(false);
211 break;
212 case SAVE_AS:
213 save(true);
214 break;
215 case CHECK:
216 check();
217 break;
218 case SOLVE:
219 solve();
220 break;
221 case QUIT:
222 if (saveUnsaved()) {
223 System.exit(0);
224 }
225 break;
226 case ABOUT:
227 JOptionPane.showMessageDialog(field,
228 "Sudoku - Copyright (c) 2013 Mike Becker\nwww.uap-core.de" +
229 "\nPublished under the BSD License",
230 "Sudoku", JOptionPane.INFORMATION_MESSAGE);
231 break;
232 default:
233 throw new UnsupportedOperationException(
234 "unknown action: " + e.getActionCommand());
235 }
236 }
238 }