Mercurial > hg > accesspd
diff java/src/uk/ac/qmul/eecs/ccmi/simpletemplate/SpeechWizardPanel.java @ 0:78b7fc5391a2
first import, outcome of NIME 2014 hackaton
author | Fiore Martin <f.martin@qmul.ac.uk> |
---|---|
date | Tue, 08 Jul 2014 16:28:59 +0100 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/java/src/uk/ac/qmul/eecs/ccmi/simpletemplate/SpeechWizardPanel.java Tue Jul 08 16:28:59 2014 +0100 @@ -0,0 +1,319 @@ +/* + CCmI Editor - A Collaborative Cross-Modal Diagram Editing Tool + + Copyright (C) 2011 Queen Mary University of London (http://ccmi.eecs.qmul.ac.uk/) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +package uk.ac.qmul.eecs.ccmi.simpletemplate; + +import java.awt.Color; +import java.awt.Component; +import java.awt.Container; +import java.awt.FlowLayout; +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; +import java.awt.Insets; +import java.awt.event.KeyAdapter; +import java.awt.event.KeyEvent; +import java.text.MessageFormat; +import java.util.Collection; +import java.util.ResourceBundle; + +import javax.swing.DefaultComboBoxModel; +import javax.swing.JComboBox; +import javax.swing.JComponent; +import javax.swing.JFormattedTextField; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.JScrollPane; +import javax.swing.JSeparator; +import javax.swing.JSpinner; +import javax.swing.JTextField; +import javax.swing.SpinnerModel; +import javax.swing.SwingConstants; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; + +import jwizardcomponent.JWizardComponents; +import jwizardcomponent.JWizardPanel; +import uk.ac.qmul.eecs.ccmi.gui.LoopComboBox; +import uk.ac.qmul.eecs.ccmi.speech.NarratorFactory; +import uk.ac.qmul.eecs.ccmi.speech.SpeechUtilities; + +/* + * The abstract class providing basic implementation for the panels displayed when the template + * wizard is run in order to build a diagram template. Subclasses will define the central component + * displayed in the panel. The central component is an input component (e.g. a JTextField), + * through which the user enters the input required for at that particular step of the wizard. + * + * + * @see Wizard + */ +@SuppressWarnings("serial") +abstract class SpeechWizardPanel extends JWizardPanel { + public SpeechWizardPanel(JWizardComponents wizardComponents, String title, int next, int previous){ + super(wizardComponents,title); + label = new JLabel(title); + this.next = next; + this.previous = previous; + } + + @Override + public void update(){ + Component focusOwner = assignFocus(); + NarratorFactory.getInstance().speak( + new StringBuilder(getPanelTitle()) + .append(' ') + .append(SpeechUtilities.getComponentSpeech(focusOwner)).toString()); + super.update(); + } + + @Override + public void setPanelTitle(String title){ + label.setText(title); + super.setPanelTitle(title); + } + + protected Component assignFocus(){ + if(component != null) + component.requestFocus(); + return component; + } + + /** + * Lays out the components according to the layout manager. This method is used by subclasses + * by passing the component the user use for input (e.g. a text field or a combo-box) as argument. + * such component is placed at the centre of the panel above the buttons. + * @param centralComponent the component to be laid out at the centre dialog + */ + protected void layoutComponents(JComponent centralComponent){ + component = centralComponent; + /* pressing enter on the central component results in a switch to the next panel */ + component.addKeyListener(new KeyAdapter(){ + @Override + public void keyPressed(KeyEvent evt){ + pressed = true; + } + + @Override + public void keyTyped(KeyEvent evt){ + /* switch on the next panel only if the press button started on the same window * + * this is to avoid keyTyped to be called after the panel switch and therefore refer * + * to a component different that the one the user pressed OK on */ + if(evt.getKeyChar() == '\n' && pressed) + getWizardComponents().getNextButton().doClick(); + pressed = false; + } + boolean pressed = false; + }); + + GridBagConstraints constr = new GridBagConstraints(); + constr.gridx = 0; + constr.gridy = 0; + constr.gridwidth = 1; + constr.gridheight = 1; + constr.weightx = 1.0; + constr.weighty = 0.0; + constr.anchor = GridBagConstraints.PAGE_START; + constr.fill = GridBagConstraints.BOTH; + constr.insets = new Insets(5, 5, 5, 5); + constr.ipadx = 0; + constr.ipady = 0; + + /* Label */ + setLayout(new GridBagLayout()); + JPanel labelPanel = new JPanel(new FlowLayout(FlowLayout.LEFT)); + label.setHorizontalAlignment(SwingConstants.LEADING); + labelPanel.add(label); + add(labelPanel,constr); + + /* JSeparator */ + constr.gridy = 1; + constr.anchor = GridBagConstraints.WEST; + constr.fill = GridBagConstraints.BOTH; + constr.insets = new Insets(1, 1, 1, 1); + add(new JSeparator(), constr); + + /* central component */ + Container centralComponentContainer; + if(centralComponent instanceof JScrollPane ){ + centralComponentContainer = centralComponent; + }else{ + centralComponentContainer = new JPanel(new GridBagLayout()); + centralComponentContainer.add(centralComponent + , new GridBagConstraints(0, 0, 1, 1, 0.0, 0.0 + , GridBagConstraints.CENTER, GridBagConstraints.BOTH + , new Insets(0, 0, 0, 0), 0, 0)); + } + constr.gridy = 2; + constr.weighty = 1.0; + constr.anchor = GridBagConstraints.CENTER; + constr.insets = new Insets(0, 0, 0, 0); + add(centralComponentContainer,constr); + } + + @Override + public void next(){ + switchPanel(next); + } + + @Override + public void back(){ + switchPanel(previous); + } + + private JLabel label; + private int next; + private int previous; + private JComponent component; + public static int OWN_SWITCH = -1; + public static int DISABLE_SWITCH = -2; +} + +@SuppressWarnings("serial") +class SelectWizardPanel extends SpeechWizardPanel { + SelectWizardPanel(JWizardComponents wizardComponents, String title, Collection<String> options, int next, int previous, Model.Record record){ + super(wizardComponents,title,next,previous); + String[] optionsArray = new String[options.size()]; + comboBox = new LoopComboBox(new DefaultComboBoxModel(options.toArray(optionsArray))); + comboBox.addItemListener(SpeechUtilities.getSpeechComboBoxItemListener()); + layoutComponents(comboBox); + this.record = record; + } + + SelectWizardPanel(JWizardComponents wizardComponents, String title, Collection<String> options, int[] nexts, int previous, Model.Record record){ + this(wizardComponents, title, options, OWN_SWITCH, previous, record); + this.nexts = nexts; + } + + SelectWizardPanel(JWizardComponents wizardComponents, String title, Collection<String> options, int[] nexts, int previous){ + this(wizardComponents, title, options, nexts, previous,null); + } + + @Override + public void next(){ + if(record != null) + record.value = (String)comboBox.getSelectedItem(); + if(nexts != null) + switchPanel(nexts[comboBox.getSelectedIndex()]); + else + super.next(); + } + + @Override + public void update(){ + if(record != null) + comboBox.setSelectedItem(record.value); + super.update(); + } + + JComboBox comboBox; + int[] nexts; + Model.Record record; +} + +@SuppressWarnings("serial") +class TextWizardPanel extends SpeechWizardPanel { + TextWizardPanel(JWizardComponents wizardComponents, String title, Collection<String> existingValues, int next, int previous, Model.Record record){ + super(wizardComponents,title,next,previous); + textField = new JTextField(); + textField.setColumns(10); + textField.addKeyListener(SpeechUtilities.getSpeechKeyListener(true)); + layoutComponents(textField); + this.record = record; + this.existingValues = existingValues; + } + + public void next(){ + String text = textField.getText().trim(); + /* if the user enters a text he has already entered (that is, it's in the existingValues the don't go on */ + /* and notify the user they have to chose another text. The only exception is when the record contains */ + /* the same text the user entered as that means they are going through the editing of an existing element*/ + if(text.isEmpty()||"\n".equals(text)){ + NarratorFactory.getInstance().speak(ResourceBundle.getBundle(SpeechWizardDialog.class.getName()).getString("dialog.error.empty_text")); + return; + } + for(String value : existingValues){ + if(value.equals(text) && !text.equals(record.value)){ + NarratorFactory.getInstance().speak(MessageFormat.format( + ResourceBundle.getBundle(SpeechWizardDialog.class.getName()).getString("dialog.error.existing_value"), + text)); + return; + } + } + if(record != null) + record.value = text; + super.next(); + } + + @Override + public void update(){ + if(record != null) + textField.setText(record.value); + super.update(); + } + + JTextField textField; + Collection<String> existingValues; + Model.Record record; +} + +@SuppressWarnings("serial") +class SpinnerWizardPanel extends SpeechWizardPanel{ + public SpinnerWizardPanel(JWizardComponents wizardComponents, String title, SpinnerModel spinnerModel, int next, int previous, Model.Record record){ + super(wizardComponents,title,next,previous); + this.record = record; + spinner = new JSpinner(spinnerModel); + spinner.addChangeListener(new ChangeListener(){ + @Override + public void stateChanged(ChangeEvent evt) { + JSpinner s = (JSpinner)(evt.getSource()); + NarratorFactory.getInstance().speak(s.getValue().toString()); + } + }); + JFormattedTextField tf = ((JSpinner.DefaultEditor)spinner.getEditor()).getTextField(); + tf.setEditable(false); + tf.setFocusable(false); + tf.setBackground(Color.white); + layoutComponents(spinner); + } + + @Override + public void next(){ + if(record != null) + record.value = spinner.getValue().toString(); + super.next(); + } + + @Override + public void update(){ + if(record != null){ + if(!record.value.isEmpty()) + spinner.setValue(Integer.parseInt(record.value)); + } + super.update(); + } + + Model.Record record; + JSpinner spinner; +} + +@SuppressWarnings("serial") +class DummyWizardPanel extends JWizardPanel{ + DummyWizardPanel(JWizardComponents wizardComponents){ + super(wizardComponents); + } +}