src/main/java/de/uapcore/sudoku/ActionHandler.java

changeset 10
369903afbb29
parent 9
576e7a2861ae
child 12
1c62c6009161
equal deleted inserted replaced
9:576e7a2861ae 10:369903afbb29
1 /* 1 /*
2 * Copyright 2013 Mike Becker. All rights reserved. 2 * Copyright 2013 Mike Becker. All rights reserved.
3 * 3 *
4 * Redistribution and use in source and binary forms, with or without 4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met: 5 * modification, are permitted provided that the following conditions are met:
6 * 6 *
7 * 1. Redistributions of source code must retain the above copyright 7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer. 8 * notice, this list of conditions and the following disclaimer.
9 * 9 *
10 * 2. Redistributions in binary form must reproduce the above copyright 10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the 11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution. 12 * documentation and/or other materials provided with the distribution.
13 * 13 *
14 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 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 15 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
18 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 18 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31 import java.awt.event.ActionListener; 31 import java.awt.event.ActionListener;
32 import java.io.File; 32 import java.io.File;
33 import java.io.IOException; 33 import java.io.IOException;
34 34
35 /** 35 /**
36 * 36 * Handles all user issued actions in the application.
37 * @author mike
38 */ 37 */
39 public final class ActionHandler implements ActionListener { 38 public final class ActionHandler implements ActionListener {
40 39
41 public static final String SAVE = "save"; 40 public static final String SAVE = "save";
42 public static final String CHECK = "check"; 41 public static final String CHECK = "check";
43 public static final String SOLVE = "solve"; 42 public static final String SOLVE = "solve";
44 43
45 public static final String NEW = "new"; 44 public static final String NEW = "new";
46 public static final String OPEN = "open"; 45 public static final String OPEN = "open";
47 public static final String SAVE_AS = "save as"; 46 public static final String SAVE_AS = "save as";
48 public static final String QUIT = "quit"; 47 public static final String QUIT = "quit";
49 public static final String ABOUT = "about"; 48 public static final String ABOUT = "about";
50 49
51 private Field field; 50 private Field field;
52 private Solver solver; 51 private Solver solver;
53 private DocumentHandler doc; 52 private DocumentHandler doc;
54 53
54 /**
55 * Constructs a new action handler instance.
56 *
57 * @param f a reference to the playing field
58 */
55 public ActionHandler(Field f) { 59 public ActionHandler(Field f) {
56 field = f; 60 field = f;
57 solver = new Solver(); 61 solver = new Solver();
58 doc = new DocumentHandler(); 62 doc = new DocumentHandler();
59 } 63 }
60 64
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 */
61 private boolean chooseSaveFilename() { 72 private boolean chooseSaveFilename() {
62 JFileChooser fc = new JFileChooser("."); 73 JFileChooser fc = new JFileChooser(".");
63 fc.setMultiSelectionEnabled(false); 74 fc.setMultiSelectionEnabled(false);
64 if (fc.showSaveDialog(field) == JFileChooser.APPROVE_OPTION) { 75 if (fc.showSaveDialog(field) == JFileChooser.APPROVE_OPTION) {
65 File f = fc.getSelectedFile(); 76 File f = fc.getSelectedFile();
79 } 90 }
80 } else { 91 } else {
81 return false; 92 return false;
82 } 93 }
83 } 94 }
84 95
96 /**
97 * Prompts the user for a file to open and, if approved, loads that file.
98 */
85 private void open() { 99 private void open() {
86 JFileChooser fc = new JFileChooser("."); 100 JFileChooser fc = new JFileChooser(".");
87 fc.setMultiSelectionEnabled(false); 101 fc.setMultiSelectionEnabled(false);
88 if (fc.showOpenDialog(field) == JFileChooser.APPROVE_OPTION) { 102 if (fc.showOpenDialog(field) == JFileChooser.APPROVE_OPTION) {
89 File f = fc.getSelectedFile(); 103 File f = fc.getSelectedFile();
90 doc.setFilename(f.getAbsolutePath()); 104 doc.setFilename(f.getAbsolutePath());
91 try { 105 try {
92 doc.load(field); 106 doc.load(field);
93 } catch (IOException e) { 107 } catch (IOException e) {
94 JOptionPane.showMessageDialog(field, 108 JOptionPane.showMessageDialog(field,
95 "Datei konnte nicht geladen werden: "+e.getMessage(), 109 "Datei konnte nicht geladen werden: " + e.getMessage(),
96 "Sudoku", JOptionPane.ERROR_MESSAGE); 110 "Sudoku", JOptionPane.ERROR_MESSAGE);
97 } 111 }
98 } 112 }
99 } 113 }
100 114
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 */
101 private boolean save(boolean rename) { 125 private boolean save(boolean rename) {
102 if (!doc.isFilenameSet() || rename) { 126 if (!doc.isFilenameSet() || rename) {
103 if (!chooseSaveFilename()) { 127 if (!chooseSaveFilename()) {
104 return false; 128 return false;
105 } 129 }
108 field.setAllCellsModified(false); 132 field.setAllCellsModified(false);
109 try { 133 try {
110 doc.save(field); 134 doc.save(field);
111 } catch (IOException e) { 135 } catch (IOException e) {
112 JOptionPane.showMessageDialog(field, 136 JOptionPane.showMessageDialog(field,
113 "Datei konnte nicht gespeichert werden: "+e.getMessage(), 137 "Datei konnte nicht gespeichert werden: " + e.getMessage(),
114 "Sudoku", JOptionPane.ERROR_MESSAGE); 138 "Sudoku", JOptionPane.ERROR_MESSAGE);
115 } 139 }
116 return true; 140 return true;
117 } else { 141 } else {
118 JOptionPane.showMessageDialog(field, 142 JOptionPane.showMessageDialog(field,
119 "Das Feld kann mit Fehlern nicht gespeichert werden!", 143 "Das Feld kann mit Fehlern nicht gespeichert werden!",
120 "Sudoku", JOptionPane.ERROR_MESSAGE); 144 "Sudoku", JOptionPane.ERROR_MESSAGE);
121 return false; 145 return false;
122 } 146 }
123 } 147 }
124 148
149 /**
150 * Checks the Sudoku field and displays the result as a dialog box.
151 */
125 private void check() { 152 private void check() {
126 if (solver.check(field)) { 153 if (solver.check(field)) {
127 JOptionPane.showMessageDialog(field, "Überprüfung erfolgreich!", 154 JOptionPane.showMessageDialog(field, "Überprüfung erfolgreich!",
128 "Sudoku", JOptionPane.INFORMATION_MESSAGE); 155 "Sudoku", JOptionPane.INFORMATION_MESSAGE);
129 } else { 156 } else {
130 JOptionPane.showMessageDialog(field, "Das Feld enthält Fehler!", 157 JOptionPane.showMessageDialog(field, "Das Feld enthält Fehler!",
131 "Sudoku", JOptionPane.WARNING_MESSAGE); 158 "Sudoku", JOptionPane.WARNING_MESSAGE);
132 } 159 }
133 } 160 }
134 161
162 /**
163 * Solves the field or displays an error dialog if the field is not solvable.
164 */
135 private void solve() { 165 private void solve() {
136 if (!solver.check(field) || !solver.solve(field)) { 166 if (!solver.check(field) || !solver.solve(field)) {
137 JOptionPane.showMessageDialog(field, "Das Feld ist nicht lösbar!", 167 JOptionPane.showMessageDialog(field, "Das Feld ist nicht lösbar!",
138 "Sudoku", JOptionPane.WARNING_MESSAGE); 168 "Sudoku", JOptionPane.WARNING_MESSAGE);
139 } 169 }
140 } 170 }
141 171
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 */
142 private boolean saveUnsaved() { 177 private boolean saveUnsaved() {
143 boolean proceed = false; 178 boolean proceed = false;
144 if (field.isAnyCellModified()) { 179 if (field.isAnyCellModified()) {
145 int result = JOptionPane.showConfirmDialog(field, 180 int result = JOptionPane.showConfirmDialog(field,
146 "Das Feld ist ungespeichert - jetzt speichern?", 181 "Das Feld ist ungespeichert - jetzt speichern?",
153 proceed = true; 188 proceed = true;
154 } 189 }
155 } else { 190 } else {
156 proceed = true; 191 proceed = true;
157 } 192 }
158 193
159 return proceed; 194 return proceed;
160 } 195 }
161 196
162 @Override 197 @Override
163 public void actionPerformed(ActionEvent e) { 198 public void actionPerformed(ActionEvent e) {
164 switch (e.getActionCommand()) { 199 switch (e.getActionCommand()) {
165 case NEW: 200 case NEW:
166 if (saveUnsaved()) { 201 if (saveUnsaved()) {
167 doc.clearFilename(); 202 doc.clearFilename();
168 field.clear(); 203 field.clear();
169 } 204 }
170 break; 205 break;
171 case OPEN: 206 case OPEN:
172 open(); 207 open();
173 break; 208 break;
174 case SAVE: 209 case SAVE:
175 save(false); 210 save(false);
176 break; 211 break;
177 case SAVE_AS: 212 case SAVE_AS:
178 save(true); 213 save(true);
179 break; 214 break;
180 case CHECK: 215 case CHECK:
181 check(); 216 check();
182 break; 217 break;
183 case SOLVE: 218 case SOLVE:
184 solve(); 219 solve();
185 break; 220 break;
186 case QUIT: 221 case QUIT:
187 if (saveUnsaved()) { 222 if (saveUnsaved()) {
188 System.exit(0); 223 System.exit(0);
189 } 224 }
190 break; 225 break;
191 case ABOUT: 226 case ABOUT:
192 JOptionPane.showMessageDialog(field, 227 JOptionPane.showMessageDialog(field,
193 "Sudoku - Copyright (c) 2013 Mike Becker\nwww.uap-core.de"+ 228 "Sudoku - Copyright (c) 2013 Mike Becker\nwww.uap-core.de" +
194 "\nPublished under the BSD License", 229 "\nPublished under the BSD License",
195 "Sudoku", JOptionPane.INFORMATION_MESSAGE); 230 "Sudoku", JOptionPane.INFORMATION_MESSAGE);
196 break; 231 break;
197 default: 232 default:
198 throw new UnsupportedOperationException( 233 throw new UnsupportedOperationException(
199 "unknown action: "+e.getActionCommand()); 234 "unknown action: " + e.getActionCommand());
200 } 235 }
201 } 236 }
202 237
203 } 238 }

mercurial