package org.agile.grenoble.gui; import java.awt.BorderLayout; import java.awt.Color; import java.awt.Dimension; import java.awt.Font; import java.awt.GridLayout; import java.awt.Label; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.image.BufferedImage; import java.io.File; import java.io.IOException; import java.util.Enumeration; import java.util.Vector; import javax.imageio.ImageIO; import javax.swing.AbstractButton; import javax.swing.BorderFactory; import javax.swing.ButtonGroup; import javax.swing.ImageIcon; import javax.swing.JButton; import javax.swing.JCheckBox; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JRadioButton; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; import org.agile.grenoble.Configuration; import org.agile.grenoble.Messages; import org.agile.grenoble.questions.AnswerType; import org.agile.grenoble.questions.AnswersType; import org.agile.grenoble.questions.ConfigurationType; import org.agile.grenoble.questions.QuestionType; import org.agile.grenoble.questions.QuestionsType; import org.agile.grenoble.user.User; class MyActionLogicListener implements ActionListener, ChangeListener { AnswerType at = null; public MyActionLogicListener(AnswerType pAt) { at = pAt ; } // @Override public void actionPerformed(ActionEvent arg0) { //select or not select ? AbstractButton ab = (AbstractButton) arg0.getSource(); if (ab.isSelected()== true) { at.setSelected(AnswerType.Selected.TRUE); } else{ at.setSelected(AnswerType.Selected.FALSE); } //System.out.println("Yeh, a action is performed , my model should be updated :" +at.getLabel()) ; } // @Override public void stateChanged(ChangeEvent arg0) { //occure too often, seems selected/unselected/highligth/unhighlight //select or not select ? AbstractButton ab = (AbstractButton) arg0.getSource(); if (ab.isSelected()== true) { at.setSelected(AnswerType.Selected.TRUE); } else{ at.setSelected(AnswerType.Selected.FALSE); } //System.out.println("Yeh, a state change is detected, my model should be updated :" +at.getLabel() + "/" + at.getSelected()) ; } } /* * myCheckGroup handle the logic of a set of checkbox, * with a maximun number of selected elements */ class MyCheckGroup implements ActionListener { int iMaxSelected = -1 ; int iNbCheckedItem = 0 ; Vector<JCheckBox> v = new Vector<JCheckBox>(); /* * maximun of element selectable in this group */ MyCheckGroup(int maxSelected) { iMaxSelected = maxSelected ; } /* * add a checkbox to this list of elements */ public void add(JCheckBox aBox) { aBox.addActionListener(this); v.add(aBox); } /* * when clicking on a checkbox, checks if max is reached. And forbid the selection * if max is reached. * note : allow unselection of elements * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent) */ // @Override public void actionPerformed(ActionEvent arg0) { //select or not select ? JCheckBox cb = (JCheckBox) arg0.getSource(); if (cb.isSelected()) { iNbCheckedItem++; if (iNbCheckedItem > iMaxSelected) { for ( Enumeration<JCheckBox> e = v.elements(); e.hasMoreElements(); ) { JCheckBox value = e.nextElement(); if (value == cb) { iNbCheckedItem--; value.setSelected(false); //display each vegetable System.out.println( value ); } } } else if (iNbCheckedItem < iMaxSelected) { //nothing } else { //nothing } } else { //unselect iNbCheckedItem--; } } } /* * main graphical class * */ public class NokiaSwing extends JFrame { private static final int globalHeight = 500; private static final int globalWidth = 600; private static final long serialVersionUID = -8322709712160036058L; JPanel [] iPanel= null; JPanel iNavBar = null ; JButton nextOrTerminate = null ; JPanel welcome = null; private String userName = "undefined"; public NokiaSwing () { super(); } private void initContent() { setTitle("Nokia Test - user '" + this.userName + "'" ) ; } //temporary public void generateQuestionDisplay(QuestionsType pQuestions) throws Exception { //JPanel questionArea = new JPanel(); iPanel= generateQuestionsPanels(pQuestions); //welcome = HomePage(); //getContentPane().add(welcome); getContentPane().setBackground(Color.lightGray); iNavBar = generateNavigationBar(); pack(); repaint(); } /* * Navigation Bar (may be a standalone class soon ) * */ public JPanel generateNavigationBar() { JPanel navigationBar = new JPanel(); nextOrTerminate = new JButton("NextorTerminate"); navigationBar.add(nextOrTerminate,BorderLayout.EAST); return navigationBar ; } /* * Took a list of question, and build the panel. There's a panel per question. * */ private JPanel[] generateQuestionsPanels(QuestionsType pQuestions) throws Exception { JPanel[] questionsPanels = new JPanel[pQuestions.getQuestionArray().length]; for (int i=0; i < pQuestions.getQuestionArray().length; i++) { questionsPanels[i] = generateQuestionPanel(pQuestions.getQuestionArray()[i]); } return questionsPanels; } /** * We return a panel per question, allowing us to display several panel in the same page * or one panel per page ... * May be the change is the "Next " button inside the panel or outside it * @throws Exception * */ private JPanel generateQuestionPanel(QuestionType pQuestion) throws Exception { JPanel questionContainer = generateQuestionArea(); if (pQuestion.getConfiguration().getType() != ConfigurationType.Type.COMPLEXE) { questionContainer.setLayout(new GridLayout(pQuestion.getAnswers().getAnswerArray().length+1, 1)); Label questionText = new Label(pQuestion.getLabel()); questionContainer.add(questionText); JLabel questionMark= Utils.getImage(Configuration.getString("NokiaTest.questionLogo")); JPanel questionPanel = new JPanel(); questionPanel.setLayout(new GridLayout(1, 2)); Font font = new Font("sansserif", Font.BOLD, 16); questionText.setBackground(Color.blue); questionText.setForeground(Color.yellow); questionMark.setBackground(Color.blue); questionText.setFont(font); questionPanel.add(questionText); questionPanel.add(questionMark); questionContainer.add(questionPanel); addAnswers(pQuestion.getConfiguration(), pQuestion.getAnswers(), questionContainer); } else { //the question if made of several question JPanel childrenPanel = null ; questionContainer.setLayout(new GridLayout(pQuestion.getQuestionArray().length, 1)); for (int i=0; i < pQuestion.getQuestionArray().length; i++) { childrenPanel = generateQuestionPanel(pQuestion.getQuestionArray()[i]); questionContainer.add(childrenPanel); } //end for } //end if return questionContainer; } /* * add answers to the question panel. * */ private void addAnswers(ConfigurationType conf, AnswersType pAnswers, JPanel questionContainer) throws Exception { if (conf == null || conf.getType() == null ) { //don't add anything return ; } if (conf.getType() == ConfigurationType.Type.SINGLE) { addRadioAnswers(pAnswers,questionContainer); } else if (conf.getType() == ConfigurationType.Type.MULTIPLE) { addCheckAnswers(conf,pAnswers,questionContainer); } else { //ERROR throw new Exception("UNKNOWN question type :" + conf.getType()); } } /* * Add check box button look answers * */ private void addCheckAnswers(ConfigurationType conf,AnswersType pAnswers, JPanel questionContainer) { MyCheckGroup buttonGroup = new MyCheckGroup(conf.getNumber()) ; for (int i = 0; i< pAnswers.getAnswerArray().length; i++){ String answer = pAnswers.getAnswerArray()[i].getLabel(); JCheckBox answerText = new JCheckBox(answer); //listen to click / unclick answerText.addChangeListener(new MyActionLogicListener(pAnswers.getAnswerArray()[i])); questionContainer.add(answerText); buttonGroup.add(answerText); } } /* * Add radio button look answers * */ private void addRadioAnswers(AnswersType pAnswers, JPanel questionContainer) { ButtonGroup buttonGroup = new ButtonGroup() ; for (int i = 0; i< pAnswers.getAnswerArray().length; i++){ String answer = pAnswers.getAnswerArray()[i].getLabel(); JRadioButton answerText = new JRadioButton(answer); questionContainer.add(answerText); //listen to click / unclick answerText.addChangeListener(new MyActionLogicListener(pAnswers.getAnswerArray()[i])); buttonGroup.add(answerText); } } private JPanel generateQuestionArea() { JPanel questionArea = new JPanel(); // Preferred height is irrelevant, since using WEST region questionArea.setPreferredSize(new Dimension(globalHeight,globalWidth)); questionArea.setBorder(BorderFactory.createLineBorder (Color.blue, 2)); questionArea.setBackground(Color.white); return questionArea; } @SuppressWarnings("deprecation") public void displayFirstquestion() { initContent(); getContentPane().setBackground(Color.lightGray); //TODO remove welcome message //getContentPane().remove(welcome); getContentPane().add(iPanel[0], BorderLayout.NORTH); //TODO add i18n nextOrTerminate.setLabel("Next"); getContentPane().add(iNavBar, BorderLayout.SOUTH ); pack(); repaint(); } public void registerOnClickNavBarEvent(NokiaControler nokiaControler) { nextOrTerminate.addActionListener(nokiaControler); } public void nextQuestion(int currentQuestionIndex,boolean isLast) { getContentPane().remove(iPanel[currentQuestionIndex-1]); getContentPane().add(iPanel[currentQuestionIndex], BorderLayout.NORTH); //TODO add i18n if (isLast) { nextOrTerminate.setLabel(Messages.getString("NokiaTest.goHome") + " " + this.userName + " !"); } else { nextOrTerminate.setLabel(Messages.getString("NokiaTest.next")); } //getContentPane().add(iNavBar, BorderLayout.SOUTH ); pack(); repaint(); } public void terminateTest() { dispose(); } public void setUserName(User user) { if (user == null) { this.userName = user.getName(); } } }