f@0
|
1 /*
|
f@0
|
2 CCmI Editor - A Collaborative Cross-Modal Diagram Editing Tool
|
f@0
|
3
|
f@0
|
4 Copyright (C) 2011 Queen Mary University of London (http://ccmi.eecs.qmul.ac.uk/)
|
f@0
|
5
|
f@0
|
6 This program is free software: you can redistribute it and/or modify
|
f@0
|
7 it under the terms of the GNU General Public License as published by
|
f@0
|
8 the Free Software Foundation, either version 3 of the License, or
|
f@0
|
9 (at your option) any later version.
|
f@0
|
10
|
f@0
|
11 This program is distributed in the hope that it will be useful,
|
f@0
|
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
|
f@0
|
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
f@0
|
14 GNU General Public License for more details.
|
f@0
|
15
|
f@0
|
16 You should have received a copy of the GNU General Public License
|
f@0
|
17 along with this program. If not, see <http://www.gnu.org/licenses/>.
|
f@0
|
18 */
|
f@0
|
19
|
f@0
|
20 package uk.ac.qmul.eecs.ccmi.simpletemplate;
|
f@0
|
21
|
f@0
|
22 import java.awt.Color;
|
f@0
|
23 import java.awt.Component;
|
f@0
|
24 import java.awt.Container;
|
f@0
|
25 import java.awt.FlowLayout;
|
f@0
|
26 import java.awt.GridBagConstraints;
|
f@0
|
27 import java.awt.GridBagLayout;
|
f@0
|
28 import java.awt.Insets;
|
f@0
|
29 import java.awt.event.KeyAdapter;
|
f@0
|
30 import java.awt.event.KeyEvent;
|
f@0
|
31 import java.text.MessageFormat;
|
f@0
|
32 import java.util.Collection;
|
f@0
|
33 import java.util.ResourceBundle;
|
f@0
|
34
|
f@0
|
35 import javax.swing.DefaultComboBoxModel;
|
f@0
|
36 import javax.swing.JComboBox;
|
f@0
|
37 import javax.swing.JComponent;
|
f@0
|
38 import javax.swing.JFormattedTextField;
|
f@0
|
39 import javax.swing.JLabel;
|
f@0
|
40 import javax.swing.JPanel;
|
f@0
|
41 import javax.swing.JScrollPane;
|
f@0
|
42 import javax.swing.JSeparator;
|
f@0
|
43 import javax.swing.JSpinner;
|
f@0
|
44 import javax.swing.JTextField;
|
f@0
|
45 import javax.swing.SpinnerModel;
|
f@0
|
46 import javax.swing.SwingConstants;
|
f@0
|
47 import javax.swing.event.ChangeEvent;
|
f@0
|
48 import javax.swing.event.ChangeListener;
|
f@0
|
49
|
f@0
|
50 import jwizardcomponent.JWizardComponents;
|
f@0
|
51 import jwizardcomponent.JWizardPanel;
|
f@0
|
52 import uk.ac.qmul.eecs.ccmi.gui.LoopComboBox;
|
f@0
|
53 import uk.ac.qmul.eecs.ccmi.speech.NarratorFactory;
|
f@0
|
54 import uk.ac.qmul.eecs.ccmi.speech.SpeechUtilities;
|
f@0
|
55
|
f@0
|
56 /*
|
f@0
|
57 * The abstract class providing basic implementation for the panels displayed when the template
|
f@0
|
58 * wizard is run in order to build a diagram template. Subclasses will define the central component
|
f@0
|
59 * displayed in the panel. The central component is an input component (e.g. a JTextField),
|
f@0
|
60 * through which the user enters the input required for at that particular step of the wizard.
|
f@0
|
61 *
|
f@0
|
62 *
|
f@0
|
63 * @see Wizard
|
f@0
|
64 */
|
f@0
|
65 @SuppressWarnings("serial")
|
f@0
|
66 abstract class SpeechWizardPanel extends JWizardPanel {
|
f@0
|
67 public SpeechWizardPanel(JWizardComponents wizardComponents, String title, int next, int previous){
|
f@0
|
68 super(wizardComponents,title);
|
f@0
|
69 label = new JLabel(title);
|
f@0
|
70 this.next = next;
|
f@0
|
71 this.previous = previous;
|
f@0
|
72 }
|
f@0
|
73
|
f@0
|
74 @Override
|
f@0
|
75 public void update(){
|
f@0
|
76 Component focusOwner = assignFocus();
|
f@0
|
77 NarratorFactory.getInstance().speak(
|
f@0
|
78 new StringBuilder(getPanelTitle())
|
f@0
|
79 .append(' ')
|
f@0
|
80 .append(SpeechUtilities.getComponentSpeech(focusOwner)).toString());
|
f@0
|
81 super.update();
|
f@0
|
82 }
|
f@0
|
83
|
f@0
|
84 @Override
|
f@0
|
85 public void setPanelTitle(String title){
|
f@0
|
86 label.setText(title);
|
f@0
|
87 super.setPanelTitle(title);
|
f@0
|
88 }
|
f@0
|
89
|
f@0
|
90 protected Component assignFocus(){
|
f@0
|
91 if(component != null)
|
f@0
|
92 component.requestFocus();
|
f@0
|
93 return component;
|
f@0
|
94 }
|
f@0
|
95
|
f@0
|
96 /**
|
f@0
|
97 * Lays out the components according to the layout manager. This method is used by subclasses
|
f@0
|
98 * by passing the component the user use for input (e.g. a text field or a combo-box) as argument.
|
f@0
|
99 * such component is placed at the centre of the panel above the buttons.
|
f@0
|
100 * @param centralComponent the component to be laid out at the centre dialog
|
f@0
|
101 */
|
f@0
|
102 protected void layoutComponents(JComponent centralComponent){
|
f@0
|
103 component = centralComponent;
|
f@0
|
104 /* pressing enter on the central component results in a switch to the next panel */
|
f@0
|
105 component.addKeyListener(new KeyAdapter(){
|
f@0
|
106 @Override
|
f@0
|
107 public void keyPressed(KeyEvent evt){
|
f@0
|
108 pressed = true;
|
f@0
|
109 }
|
f@0
|
110
|
f@0
|
111 @Override
|
f@0
|
112 public void keyTyped(KeyEvent evt){
|
f@0
|
113 /* switch on the next panel only if the press button started on the same window *
|
f@0
|
114 * this is to avoid keyTyped to be called after the panel switch and therefore refer *
|
f@0
|
115 * to a component different that the one the user pressed OK on */
|
f@0
|
116 if(evt.getKeyChar() == '\n' && pressed)
|
f@0
|
117 getWizardComponents().getNextButton().doClick();
|
f@0
|
118 pressed = false;
|
f@0
|
119 }
|
f@0
|
120 boolean pressed = false;
|
f@0
|
121 });
|
f@0
|
122
|
f@0
|
123 GridBagConstraints constr = new GridBagConstraints();
|
f@0
|
124 constr.gridx = 0;
|
f@0
|
125 constr.gridy = 0;
|
f@0
|
126 constr.gridwidth = 1;
|
f@0
|
127 constr.gridheight = 1;
|
f@0
|
128 constr.weightx = 1.0;
|
f@0
|
129 constr.weighty = 0.0;
|
f@0
|
130 constr.anchor = GridBagConstraints.PAGE_START;
|
f@0
|
131 constr.fill = GridBagConstraints.BOTH;
|
f@0
|
132 constr.insets = new Insets(5, 5, 5, 5);
|
f@0
|
133 constr.ipadx = 0;
|
f@0
|
134 constr.ipady = 0;
|
f@0
|
135
|
f@0
|
136 /* Label */
|
f@0
|
137 setLayout(new GridBagLayout());
|
f@0
|
138 JPanel labelPanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
|
f@0
|
139 label.setHorizontalAlignment(SwingConstants.LEADING);
|
f@0
|
140 labelPanel.add(label);
|
f@0
|
141 add(labelPanel,constr);
|
f@0
|
142
|
f@0
|
143 /* JSeparator */
|
f@0
|
144 constr.gridy = 1;
|
f@0
|
145 constr.anchor = GridBagConstraints.WEST;
|
f@0
|
146 constr.fill = GridBagConstraints.BOTH;
|
f@0
|
147 constr.insets = new Insets(1, 1, 1, 1);
|
f@0
|
148 add(new JSeparator(), constr);
|
f@0
|
149
|
f@0
|
150 /* central component */
|
f@0
|
151 Container centralComponentContainer;
|
f@0
|
152 if(centralComponent instanceof JScrollPane ){
|
f@0
|
153 centralComponentContainer = centralComponent;
|
f@0
|
154 }else{
|
f@0
|
155 centralComponentContainer = new JPanel(new GridBagLayout());
|
f@0
|
156 centralComponentContainer.add(centralComponent
|
f@0
|
157 , new GridBagConstraints(0, 0, 1, 1, 0.0, 0.0
|
f@0
|
158 , GridBagConstraints.CENTER, GridBagConstraints.BOTH
|
f@0
|
159 , new Insets(0, 0, 0, 0), 0, 0));
|
f@0
|
160 }
|
f@0
|
161 constr.gridy = 2;
|
f@0
|
162 constr.weighty = 1.0;
|
f@0
|
163 constr.anchor = GridBagConstraints.CENTER;
|
f@0
|
164 constr.insets = new Insets(0, 0, 0, 0);
|
f@0
|
165 add(centralComponentContainer,constr);
|
f@0
|
166 }
|
f@0
|
167
|
f@0
|
168 @Override
|
f@0
|
169 public void next(){
|
f@0
|
170 switchPanel(next);
|
f@0
|
171 }
|
f@0
|
172
|
f@0
|
173 @Override
|
f@0
|
174 public void back(){
|
f@0
|
175 switchPanel(previous);
|
f@0
|
176 }
|
f@0
|
177
|
f@0
|
178 private JLabel label;
|
f@0
|
179 private int next;
|
f@0
|
180 private int previous;
|
f@0
|
181 private JComponent component;
|
f@0
|
182 public static int OWN_SWITCH = -1;
|
f@0
|
183 public static int DISABLE_SWITCH = -2;
|
f@0
|
184 }
|
f@0
|
185
|
f@0
|
186 @SuppressWarnings("serial")
|
f@0
|
187 class SelectWizardPanel extends SpeechWizardPanel {
|
f@0
|
188 SelectWizardPanel(JWizardComponents wizardComponents, String title, Collection<String> options, int next, int previous, Model.Record record){
|
f@0
|
189 super(wizardComponents,title,next,previous);
|
f@0
|
190 String[] optionsArray = new String[options.size()];
|
f@0
|
191 comboBox = new LoopComboBox(new DefaultComboBoxModel(options.toArray(optionsArray)));
|
f@0
|
192 comboBox.addItemListener(SpeechUtilities.getSpeechComboBoxItemListener());
|
f@0
|
193 layoutComponents(comboBox);
|
f@0
|
194 this.record = record;
|
f@0
|
195 }
|
f@0
|
196
|
f@0
|
197 SelectWizardPanel(JWizardComponents wizardComponents, String title, Collection<String> options, int[] nexts, int previous, Model.Record record){
|
f@0
|
198 this(wizardComponents, title, options, OWN_SWITCH, previous, record);
|
f@0
|
199 this.nexts = nexts;
|
f@0
|
200 }
|
f@0
|
201
|
f@0
|
202 SelectWizardPanel(JWizardComponents wizardComponents, String title, Collection<String> options, int[] nexts, int previous){
|
f@0
|
203 this(wizardComponents, title, options, nexts, previous,null);
|
f@0
|
204 }
|
f@0
|
205
|
f@0
|
206 @Override
|
f@0
|
207 public void next(){
|
f@0
|
208 if(record != null)
|
f@0
|
209 record.value = (String)comboBox.getSelectedItem();
|
f@0
|
210 if(nexts != null)
|
f@0
|
211 switchPanel(nexts[comboBox.getSelectedIndex()]);
|
f@0
|
212 else
|
f@0
|
213 super.next();
|
f@0
|
214 }
|
f@0
|
215
|
f@0
|
216 @Override
|
f@0
|
217 public void update(){
|
f@0
|
218 if(record != null)
|
f@0
|
219 comboBox.setSelectedItem(record.value);
|
f@0
|
220 super.update();
|
f@0
|
221 }
|
f@0
|
222
|
f@0
|
223 JComboBox comboBox;
|
f@0
|
224 int[] nexts;
|
f@0
|
225 Model.Record record;
|
f@0
|
226 }
|
f@0
|
227
|
f@0
|
228 @SuppressWarnings("serial")
|
f@0
|
229 class TextWizardPanel extends SpeechWizardPanel {
|
f@0
|
230 TextWizardPanel(JWizardComponents wizardComponents, String title, Collection<String> existingValues, int next, int previous, Model.Record record){
|
f@0
|
231 super(wizardComponents,title,next,previous);
|
f@0
|
232 textField = new JTextField();
|
f@0
|
233 textField.setColumns(10);
|
f@0
|
234 textField.addKeyListener(SpeechUtilities.getSpeechKeyListener(true));
|
f@0
|
235 layoutComponents(textField);
|
f@0
|
236 this.record = record;
|
f@0
|
237 this.existingValues = existingValues;
|
f@0
|
238 }
|
f@0
|
239
|
f@0
|
240 public void next(){
|
f@0
|
241 String text = textField.getText().trim();
|
f@0
|
242 /* if the user enters a text he has already entered (that is, it's in the existingValues the don't go on */
|
f@0
|
243 /* and notify the user they have to chose another text. The only exception is when the record contains */
|
f@0
|
244 /* the same text the user entered as that means they are going through the editing of an existing element*/
|
f@0
|
245 if(text.isEmpty()||"\n".equals(text)){
|
f@0
|
246 NarratorFactory.getInstance().speak(ResourceBundle.getBundle(SpeechWizardDialog.class.getName()).getString("dialog.error.empty_text"));
|
f@0
|
247 return;
|
f@0
|
248 }
|
f@0
|
249 for(String value : existingValues){
|
f@0
|
250 if(value.equals(text) && !text.equals(record.value)){
|
f@0
|
251 NarratorFactory.getInstance().speak(MessageFormat.format(
|
f@0
|
252 ResourceBundle.getBundle(SpeechWizardDialog.class.getName()).getString("dialog.error.existing_value"),
|
f@0
|
253 text));
|
f@0
|
254 return;
|
f@0
|
255 }
|
f@0
|
256 }
|
f@0
|
257 if(record != null)
|
f@0
|
258 record.value = text;
|
f@0
|
259 super.next();
|
f@0
|
260 }
|
f@0
|
261
|
f@0
|
262 @Override
|
f@0
|
263 public void update(){
|
f@0
|
264 if(record != null)
|
f@0
|
265 textField.setText(record.value);
|
f@0
|
266 super.update();
|
f@0
|
267 }
|
f@0
|
268
|
f@0
|
269 JTextField textField;
|
f@0
|
270 Collection<String> existingValues;
|
f@0
|
271 Model.Record record;
|
f@0
|
272 }
|
f@0
|
273
|
f@0
|
274 @SuppressWarnings("serial")
|
f@0
|
275 class SpinnerWizardPanel extends SpeechWizardPanel{
|
f@0
|
276 public SpinnerWizardPanel(JWizardComponents wizardComponents, String title, SpinnerModel spinnerModel, int next, int previous, Model.Record record){
|
f@0
|
277 super(wizardComponents,title,next,previous);
|
f@0
|
278 this.record = record;
|
f@0
|
279 spinner = new JSpinner(spinnerModel);
|
f@0
|
280 spinner.addChangeListener(new ChangeListener(){
|
f@0
|
281 @Override
|
f@0
|
282 public void stateChanged(ChangeEvent evt) {
|
f@0
|
283 JSpinner s = (JSpinner)(evt.getSource());
|
f@0
|
284 NarratorFactory.getInstance().speak(s.getValue().toString());
|
f@0
|
285 }
|
f@0
|
286 });
|
f@0
|
287 JFormattedTextField tf = ((JSpinner.DefaultEditor)spinner.getEditor()).getTextField();
|
f@0
|
288 tf.setEditable(false);
|
f@0
|
289 tf.setFocusable(false);
|
f@0
|
290 tf.setBackground(Color.white);
|
f@0
|
291 layoutComponents(spinner);
|
f@0
|
292 }
|
f@0
|
293
|
f@0
|
294 @Override
|
f@0
|
295 public void next(){
|
f@0
|
296 if(record != null)
|
f@0
|
297 record.value = spinner.getValue().toString();
|
f@0
|
298 super.next();
|
f@0
|
299 }
|
f@0
|
300
|
f@0
|
301 @Override
|
f@0
|
302 public void update(){
|
f@0
|
303 if(record != null){
|
f@0
|
304 if(!record.value.isEmpty())
|
f@0
|
305 spinner.setValue(Integer.parseInt(record.value));
|
f@0
|
306 }
|
f@0
|
307 super.update();
|
f@0
|
308 }
|
f@0
|
309
|
f@0
|
310 Model.Record record;
|
f@0
|
311 JSpinner spinner;
|
f@0
|
312 }
|
f@0
|
313
|
f@0
|
314 @SuppressWarnings("serial")
|
f@0
|
315 class DummyWizardPanel extends JWizardPanel{
|
f@0
|
316 DummyWizardPanel(JWizardComponents wizardComponents){
|
f@0
|
317 super(wizardComponents);
|
f@0
|
318 }
|
f@0
|
319 }
|