2 * Sudokuki - essential sudoku game
3 * Copyright (C) 2007-2016 Sylvain Vedrenne
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 package net.jankenpoi.sudokuki.ui.swing;
20 import java.awt.BorderLayout;
21 import java.awt.Component;
23 import java.awt.GridLayout;
24 import java.awt.event.FocusAdapter;
25 import java.awt.event.FocusEvent;
26 import java.awt.event.KeyAdapter;
27 import java.awt.event.KeyEvent;
28 import java.util.HashSet;
29 import java.util.Iterator;
31 import javax.swing.JButton;
32 import javax.swing.JCheckBox;
33 import javax.swing.JPanel;
34 import javax.swing.JToggleButton;
35 import static net.jankenpoi.i18n.I18n.gtxt;
41 @SuppressWarnings("serial")
42 public class SelectMemosPanel extends JPanel {
44 private JButton btnClear;
45 private JCheckBox[] ckb = new JCheckBox[9];
46 private int focusedElement = 4;
47 private JButton btnConfirm;
48 private JPanel panelClear = new JPanel(new GridLayout());
49 private JPanel panel789 = new JPanel(new GridLayout());
50 private JPanel panel456 = new JPanel(new GridLayout());
51 private JPanel panel123 = new JPanel(new GridLayout());
52 private JPanel panelConfirm = new JPanel(new GridLayout());
53 private HashSet<Byte> memos = new HashSet<Byte>();
54 private HashSet<Byte> previousMemos = new HashSet<Byte>();
56 private Font NORMAL_FONT = new Font("Serif", Font.PLAIN, 18);
58 private InnerKeyListener innerKeyListener = new InnerKeyListener();
59 private InnerFocusListener innerFocusListener = new InnerFocusListener();
61 private DualSelectionDialog parent;
63 public SelectMemosPanel(DualSelectionDialog parent, Byte[] previousMemos) {
66 initComponents(previousMemos);
67 parent.getTabbedPane().addKeyListener(innerKeyListener);
68 parent.getTabbedPane().addFocusListener(innerFocusListener);
71 private void configureCheckBox(JCheckBox btn, String text, final int button) {
73 btn.setFont(NORMAL_FONT);
75 btn.setToolTipText(text);
76 btn.setCursor(new java.awt.Cursor(java.awt.Cursor.HAND_CURSOR));
77 btn.addActionListener(new java.awt.event.ActionListener() {
78 public void actionPerformed(java.awt.event.ActionEvent evt) {
79 buttonClicked(button);
82 btn.addKeyListener(innerKeyListener);
83 btn.addFocusListener(innerFocusListener);
86 private void initComponents(Byte[] previousMemos) {
88 if (previousMemos != null) {
89 for (int i = 0; i < previousMemos.length; i++) {
90 memos.add(previousMemos[i]);
91 this.previousMemos.add(previousMemos[i]);
94 for (int i = 0; i < ckb.length; i++) {
95 ckb[i] = new JCheckBox(String.valueOf(i+1));
97 btnConfirm = new JButton();
99 btnClear = new JButton();
100 btnClear.setText(gtxt("Clear memos"));
101 btnClear.setEnabled(true);
102 btnClear.addActionListener(new java.awt.event.ActionListener() {
103 public void actionPerformed(java.awt.event.ActionEvent evt) {
106 private void clearClicked() {
107 for (byte i=1; i<=ckb.length; i++) {
108 memos.remove(Byte.valueOf(i));
109 ckb[i-1].setSelected(false);
113 btnClear.addKeyListener(innerKeyListener);
114 btnClear.addFocusListener(innerFocusListener);
115 configureCheckBox(ckb[6], "7", 6);
116 configureCheckBox(ckb[7], "8", 7);
117 configureCheckBox(ckb[8], "9", 8);
118 configureCheckBox(ckb[3], "4", 3);
119 configureCheckBox(ckb[4], "5", 4);
120 configureCheckBox(ckb[5], "6", 5);
121 configureCheckBox(ckb[0], "1", 0);
122 configureCheckBox(ckb[1], "2", 1);
123 configureCheckBox(ckb[2], "3", 2);
124 btnConfirm.setText(gtxt("Ok"));
125 btnConfirm.setEnabled(true);
126 btnConfirm.addActionListener(new java.awt.event.ActionListener() {
127 public void actionPerformed(java.awt.event.ActionEvent evt) {
131 private void confirmClicked() {
132 parent.memosPanelConfirmed();
135 btnConfirm.addKeyListener(innerKeyListener);
136 btnConfirm.addFocusListener(innerFocusListener);
138 Iterator<Byte> it = memos.iterator();
139 while (it.hasNext()) {
140 JToggleButton button = ckb[it.next().intValue()-1];
141 button.setSelected(true);
145 GridLayout btnLayout = new GridLayout(5, 1);
146 setLayout(btnLayout);
153 panelClear.add(btnClear);
154 panel789.add(ckb[6], BorderLayout.LINE_START);
155 panel789.add(ckb[7], BorderLayout.CENTER);
156 panel789.add(ckb[8], BorderLayout.LINE_END);
157 panel456.add(ckb[3], BorderLayout.LINE_START);
158 panel456.add(ckb[4], BorderLayout.CENTER);
159 panel456.add(ckb[5], BorderLayout.LINE_END);
160 panel123.add(ckb[0], BorderLayout.LINE_START);
161 panel123.add(ckb[1], BorderLayout.CENTER);
162 panel123.add(ckb[2], BorderLayout.LINE_END);
163 panelConfirm.add(btnConfirm);
165 ckb[4].requestFocusInWindow();
169 private boolean isTabSelected() {
170 int idx = parent.getTabbedPane().getSelectedIndex();
174 private void buttonClicked(int button) {
175 byte value = (byte)(button + 1);
176 if (ckb[button].isSelected()) {
177 memos.add(Byte.valueOf(value));
179 memos.remove(Byte.valueOf(value));
183 public byte[] getSelectedMemos() {
184 byte[] memosArray = new byte[memos.size()];
186 Iterator<Byte> it = memos.iterator();
188 while (it.hasNext()) {
189 memosArray[i] = it.next().byteValue();
195 private class InnerKeyListener extends KeyAdapter {
197 public void keyPressed(KeyEvent ke) {
198 if (isTabSelected() && focusedTabPane()) {
199 int code = ke.getKeyCode();
200 if (code == KeyEvent.VK_H) {
201 int index = parent.getTabbedPane().getSelectedIndex();
202 int newIndex = (index == 0)?1:0;
203 parent.getTabbedPane().setSelectedIndex(newIndex);
204 parent.getTabbedPane().requestFocusInWindow();
207 else if (code == KeyEvent.VK_L) {
211 if (!isTabSelected()) {
214 int code = ke.getKeyCode();
215 if (code == KeyEvent.VK_KP_UP || code == KeyEvent.VK_UP || code == KeyEvent.VK_K) {
216 if (focusedTabPane()) {
219 if (focusedClearButton()) {
220 parent.getTabbedPane().requestFocusInWindow();
223 if (focusedOkButton()) {
224 ckb[focusedElement].requestFocusInWindow();
227 if (focusedElement / 3 == 0) {
228 btnClear.requestFocusInWindow();
231 focusedElement = Math.max(0, focusedElement-3);
232 ckb[focusedElement].requestFocusInWindow();
234 else if (code == KeyEvent.VK_KP_DOWN || code == KeyEvent.VK_DOWN || code == KeyEvent.VK_J) {
235 if (focusedTabPane()) {
236 btnClear.requestFocusInWindow();
239 if (focusedOkButton()) {
242 if (focusedClearButton()) {
244 ckb[focusedElement].requestFocusInWindow();
247 if (focusedElement / 3 == 2) {
248 btnConfirm.requestFocusInWindow();
251 focusedElement = Math.min(8, focusedElement+3);
252 ckb[focusedElement].requestFocusInWindow();
254 else if (code == KeyEvent.VK_KP_LEFT || code == KeyEvent.VK_LEFT || code == KeyEvent.VK_H) {
255 if (focusedElement%3 == 0 || btnConfirm.hasFocus() || btnClear.hasFocus()) {
258 focusedElement = Math.max(0, focusedElement-1);
259 ckb[focusedElement].requestFocusInWindow();
261 else if (code == KeyEvent.VK_KP_RIGHT || code == KeyEvent.VK_RIGHT || code == KeyEvent.VK_L) {
262 if (focusedElement%3 == 2 || focusedOkButton() || focusedClearButton()) {
265 focusedElement = Math.min(8, focusedElement+1);
266 ckb[focusedElement].requestFocusInWindow();
268 else if (code == KeyEvent.VK_ESCAPE) {
269 parent.memosPanelEscaped();
273 private boolean focusedTabPane() {
274 return parent.getTabbedPane().hasFocus();
278 public void keyReleased(KeyEvent ke) {
279 if (!isTabSelected()) {
282 int code = ke.getKeyCode();
283 if (code == KeyEvent.VK_ENTER) {
284 if (focusedClearButton() || focusedOkButton()) {
286 * Buttons actions are managing this so Nothing to do.
290 parent.memosPanelConfirmed();
296 private class InnerFocusListener extends FocusAdapter {
299 public void focusGained(FocusEvent e) {
301 Component comp = e.getComponent();
302 if (comp == ckb[focusedElement]) {
305 for (int i=0; i<ckb.length; i++) {
306 if (comp == ckb[i]) {
314 private boolean focusedOkButton() {
315 return btnConfirm.hasFocus();
318 private boolean focusedClearButton() {
319 return btnClear.hasFocus();
322 public boolean memosChanged() {
323 if (previousMemos.equals(memos)) {