View Javadoc

1   /***
2    * Created on Jan 10, 2006, Copyright UC Regents
3    */
4   package org.telscenter.pas.steps.quickEditors.qti.assessment;
5   
6   import info.clearthought.layout.TableLayout;
7   
8   import java.awt.BorderLayout;
9   import java.awt.Dimension;
10  import java.awt.Font;
11  import java.awt.GridLayout;
12  import java.awt.event.ActionEvent;
13  import java.awt.event.ActionListener;
14  import java.awt.event.FocusEvent;
15  import java.awt.event.FocusListener;
16  import java.io.Serializable;
17  import java.util.Iterator;
18  import java.util.List;
19  
20  import javax.swing.AbstractAction;
21  import javax.swing.Action;
22  import javax.swing.BorderFactory;
23  import javax.swing.JButton;
24  import javax.swing.JLabel;
25  import javax.swing.JPanel;
26  import javax.swing.JRadioButton;
27  import javax.swing.JTextField;
28  import javax.swing.SwingConstants;
29  import javax.swing.undo.UndoManager;
30  import javax.xml.bind.JAXBElement;
31  
32  import net.miginfocom.swing.MigLayout;
33  
34  import org.apache.commons.lang.StringUtils;
35  import org.imsglobal.xsd.imsqti_v2p0.ChoiceInteractionType;
36  import org.imsglobal.xsd.imsqti_v2p0.FeedbackInlineType;
37  import org.imsglobal.xsd.imsqti_v2p0.ResponseDeclarationType;
38  import org.imsglobal.xsd.imsqti_v2p0.SimpleChoiceType;
39  import org.telscenter.pas.common.ui.CommonUI;
40  import org.telscenter.pas.common.ui.panel.TextEditorPanel;
41  import org.telscenter.pas.steps.quickEditors.icons.ToolIconProvider;
42  
43  
44  /***
45   * @author aperritano
46   */
47  public class ChoiceCardUI extends JPanel {
48  
49  	/***
50  	 * 
51  	 */
52  	private static final int choiceTextFieldLength = CardConstants.TEXT_AREA_LENTH-65;
53  
54  	private JButton addButton;
55  
56  	private JButton deleteButton;
57  
58  	private JPanel formPanel;
59  
60  	private JLabel choiceNumberLabel;
61  
62  	private JTextField choiceText;
63  
64  	private SimpleChoiceType simpleChoice;
65  
66  	private int choiceNumber;
67  
68  	private JRadioButton correctAnswerRadio;
69  
70  	private Font boldFont;
71  
72  	private boolean needsHeader;
73  
74  	private ChoiceInteractionType choiceInteraction;
75  
76  	private ResponseDeclarationType responseDeclaratoinType;
77  
78  	private boolean hasCorrectAnswer;
79  
80  	public JLabel feedbackLabel;
81  
82  	private FeedbackInlineType inlineFeedback;
83  
84  	private UndoManager undoManager;
85  
86  	public ChoiceCardUI() {
87  		super();
88  	}
89  
90  	/***
91  	 * @param hasCorrectAnswer 
92  	 * @param choiceInteraction 
93  	 * @param simpleChoice
94  	 * @param responseDeclarationType 
95  	 * @param undoManager 
96  	 */
97  	public ChoiceCardUI(boolean hasCorrectAnswer, ChoiceInteractionType choiceInteraction, SimpleChoiceType simpleChoice, ResponseDeclarationType responseDeclarationType, UndoManager undoManager) {
98  		super();
99  		this.hasCorrectAnswer = hasCorrectAnswer;
100 		this.choiceInteraction = choiceInteraction;
101 		this.simpleChoice = simpleChoice;
102 		this.responseDeclaratoinType = responseDeclarationType;
103 		this.undoManager = undoManager;
104 		inlineFeedback = isInlineFeedback();
105 		
106 		createMainUI();
107 	}
108 
109 	protected void createMainUI() {
110 		this.setLayout(new BorderLayout(0, 0));
111 		this.setOpaque(false);
112 		//this.setBorder(BorderFactory.createEmptyBorder(2, 2, 2, 2));
113 		this.add(createMainArea(), BorderLayout.CENTER);
114 	}
115 
116 	public void setChoiceNumber(int choiceNumber) {
117 		this.choiceNumber = choiceNumber;
118 		choiceNumberLabel.setText("Choice " +choiceNumber + ".");
119 		
120 		if( inlineFeedback != null )
121 		feedbackLabel.setText("Choice " +choiceNumber + " Feedback");
122 	}
123 
124 	public void enableAdd(boolean flag) {
125 		addButton.setEnabled(flag);
126 	}
127 
128 	public void enableDelete(boolean flag) {
129 		deleteButton.setEnabled(flag);
130 	}
131 
132 	/***
133 	 * @return
134 	 */
135 	protected JPanel createMainArea() {
136 
137 		formPanel = new JPanel(new MigLayout("insets 4"));
138 
139 		double pref = TableLayout.PREFERRED;
140 		double fill = TableLayout.FILL;
141 		double hSpace = 5;
142 		// this must be the same as the one in CardHeaderUI
143 			formPanel.add(createInputRow(),"growx");
144 
145 		formPanel.setOpaque(false);
146 //		formPanel.setBorder(BorderFactory.createEmptyBorder(2, 2, 2, 2));
147 		return formPanel;
148 	}
149 
150 	/***
151 	 * creates the row used for inline feedback
152 	 * 
153 	 * @param formPanel2
154 	 * @param inlineFeedback
155 	 */
156 	protected void createInLineFeedbackRow(JPanel feedPanel,
157 			final FeedbackInlineType inlineFeedback) {
158 		
159 		if( hasCorrectAnswer ) {
160 			feedPanel.add(new JLabel(" "));
161 		}
162 		feedbackLabel = new JLabel("Feedback:");
163 		feedbackLabel.setFont(boldFont);
164 		feedbackLabel.setHorizontalAlignment(SwingConstants.LEFT);
165 		feedbackLabel.setVerticalTextPosition(SwingConstants.NORTH);
166 		feedbackLabel.setOpaque(false);
167 
168 		feedPanel.add(feedbackLabel);
169 
170 		final JTextField feedText = new JTextField();
171 		//feedText.setBackground(this.getBackground());
172 		if( undoManager != null)
173 			feedText.getDocument().addUndoableEditListener(undoManager);
174 		
175 		String feedbackString = null;
176 		
177 		List<Serializable> content = inlineFeedback.getContent();
178 		for (Serializable item : content) {
179 			if( item instanceof String) {
180 				feedbackString = (String) item;
181 			}
182 		}// for
183 		feedText.setPreferredSize(new Dimension(choiceTextFieldLength, choiceText.getSize().height));
184 		feedText.setText(feedbackString);
185 		 
186 		feedText.putClientProperty(CardConstants.SIMPLE_CHOICE, simpleChoice);
187 		feedText.putClientProperty(CardConstants.INTERACTION, choiceInteraction);
188 		feedText.putClientProperty(CardConstants.INLINEFEEDBACK, inlineFeedback);
189 		
190 		feedText.addFocusListener(new FocusListener(){
191 
192 			public void focusGained(FocusEvent e) {
193 				// TODO Auto-generated method stub
194 				
195 			}
196 
197 			public void focusLost(FocusEvent e) {
198 				JTextField source = (JTextField) e.getSource();
199 				String text = source.getText();
200 				System.out.println("NEW CHOICE: " + text);
201 				
202 				SimpleChoiceType  sc = (SimpleChoiceType) source.getClientProperty(CardConstants.SIMPLE_CHOICE);
203 				ChoiceInteractionType ci = (ChoiceInteractionType) source.getClientProperty(CardConstants.INTERACTION);
204 				FeedbackInlineType feedbackType = (FeedbackInlineType) source.getClientProperty(CardConstants.INLINEFEEDBACK);
205 				
206 				int oldIndex = ci.getSimpleChoice().indexOf(sc);
207 				
208 				if( !sc.getContent().isEmpty() ) {
209 					//doubly remove and then add
210 					
211 					List<Serializable> choiceContent = sc.getContent();
212 					for (Serializable serializable : choiceContent) {
213 						if (serializable instanceof JAXBElement) {
214 							JAXBElement<FeedbackInlineType> jaxbElement = (JAXBElement<FeedbackInlineType>) serializable;
215 							Object contentItem = jaxbElement.getValue();
216 							if (contentItem instanceof FeedbackInlineType) {
217 								FeedbackInlineType inlineFeedbackItem = (FeedbackInlineType) contentItem;
218 								List<Serializable> feedbackContent = inlineFeedback.getContent();
219 								
220 								//check if there is already inline feedback content
221 								if(feedbackContent.size() > 0) {
222 									//remove it
223 									inlineFeedbackItem.getContent().remove(0);
224 								}
225 								
226 								//add new text
227 								inlineFeedbackItem.getContent().add(0, text);
228 							}
229 						}
230 					}//for
231 					
232 					
233 					//sc.getContent().remove(0);
234 				}
235 				//sc.getContent().add(text);
236 				//replace the existing one
237 				choiceInteraction.getSimpleChoice().remove(oldIndex);
238 				choiceInteraction.getSimpleChoice().add(oldIndex, sc);
239 				
240 				System.out.println("NEW CHOICE: " + ci.getSimpleChoice().toString());
241 			}});
242 
243 
244 		
245 		
246 		 feedPanel.add(feedText,"growx");
247 	}
248 
249 	protected JPanel createInputRow() {
250 		// FIXME this needs to set the correct response in the Response
251 		// Declaration
252 		
253 		JPanel choicePanel = new JPanel();
254 		choicePanel.setOpaque(false);
255 		if( hasCorrectAnswer ) {
256 			choicePanel.setLayout(new MigLayout("wrap 4, insets 0"));
257 			correctAnswerRadio = new JRadioButton();
258 		// correctAnswerRadio.setText("bob");
259 		
260 		//check it if it is the correct answer
261 		if( simpleChoice.getIdentifier().equals(responseDeclaratoinType.getCorrectResponse().getInterpretation())) {
262 			correctAnswerRadio.setSelected(true);
263 		}
264 		
265 		correctAnswerRadio.setOpaque(false);
266 		correctAnswerRadio.setHorizontalAlignment(JRadioButton.CENTER);
267 		correctAnswerRadio.putClientProperty(CardConstants.SIMPLE_CHOICE_ID, simpleChoice.getIdentifier());
268 		correctAnswerRadio.addActionListener(new ActionListener() {
269 
270 			public void actionPerformed(ActionEvent e) {
271 				JRadioButton source = (JRadioButton)e.getSource();
272 				if( source.isSelected() ) {
273 					String id = (String) source.getClientProperty(CardConstants.SIMPLE_CHOICE_ID);
274 					responseDeclaratoinType.getCorrectResponse().setInterpretation(id);
275 					System.out.println("new correct answer is: " + id);
276 				} 
277 			}});
278 			choicePanel.add(correctAnswerRadio);
279 		} else {
280 			choicePanel.setLayout(new MigLayout("wrap 3, insets 0"));
281 		}
282 		choiceNumberLabel = new JLabel("Choice 1.");
283 		choiceNumberLabel.setFont(boldFont);
284 		choiceNumberLabel.setHorizontalAlignment(SwingConstants.LEFT);
285 		choiceNumberLabel.setVerticalTextPosition(SwingConstants.NORTH);
286 		choiceNumberLabel.setOpaque(false);
287 
288 	
289 		choicePanel.add(choiceNumberLabel);
290 
291 		choiceText = new JTextField();
292 		choiceText.setPreferredSize(new Dimension(choiceTextFieldLength, choiceText.getSize().height));
293 	//	choiceText.setBackground(this.getBackground());
294 		//choiceText.setEditable(false);
295 		choiceText.setText(getChoiceText());
296 		
297 		if( undoManager != null )
298 			choiceText.getDocument().addUndoableEditListener(undoManager);
299 		
300 		choiceText.putClientProperty(CardConstants.SIMPLE_CHOICE, simpleChoice);
301 		choiceText.putClientProperty(CardConstants.INTERACTION, choiceInteraction);
302 		choiceText.addFocusListener(new FocusListener(){
303 
304 			public void focusGained(FocusEvent e) {
305 				// TODO Auto-generated method stub
306 				
307 			}
308 
309 			public void focusLost(FocusEvent e) {
310 				JTextField textfield = (JTextField)e.getSource();
311 				String cp = (String) textfield.getClientProperty(CommonUI.MODE);
312 				String text = textfield.getText();
313 				
314 				System.out.println("NEW CHOICE: " + text);
315 				
316 				SimpleChoiceType  sc = (SimpleChoiceType) textfield.getClientProperty(CardConstants.SIMPLE_CHOICE);
317 				ChoiceInteractionType ci = (ChoiceInteractionType) textfield.getClientProperty(CardConstants.INTERACTION);
318 				
319 				int oldIndex = ci.getSimpleChoice().indexOf(sc);
320 				
321 				if( !sc.getContent().isEmpty() ) {
322 					//doubly remove and then add
323 					
324 					List<Serializable> choiceContent = sc.getContent();
325 					Iterator<Serializable> iterator = choiceContent.iterator();
326 					for (Iterator it1 = choiceContent.iterator(); it1
327 							.hasNext();) {
328 						Serializable s1 = (Serializable) it1
329 								.next();
330 						if (s1 instanceof String) {
331 							it1.remove();
332 						}// if
333 						
334 					}
335 
336 				}
337 				sc.getContent().add(text);
338 				//replace the existing one
339 				choiceInteraction.getSimpleChoice().remove(oldIndex);
340 				choiceInteraction.getSimpleChoice().add(oldIndex, sc);
341 				
342 				System.out.println("NEW CHOICE: " + ci.getSimpleChoice().toString());
343 			}});
344 
345 		
346 		//TextEditorPanel ppanel = new TextEditorPanel(choiceText,new Dimension(CardConstants.TEXT_AREA_LENTH, choiceText.getSize().height));
347 		 
348 //		JButton jb = ppanel.getEditButton();
349 //		jb.putClientProperty(CardConstants.SIMPLE_CHOICE, simpleChoice);
350 //		jb.putClientProperty(CardConstants.INTERACTION, choiceInteraction);
351 		
352 		choicePanel.add(choiceText,"growx");
353 		choicePanel.add(createButtonPanel());
354 		
355 		
356 		
357 		if(inlineFeedback != null){
358 			createInLineFeedbackRow(choicePanel, inlineFeedback);
359 		}
360 		
361 		
362 		return choicePanel;
363 	}
364 
365 	/***
366 	 * @return
367 	 */
368 	protected String getChoiceText() {
369 		
370 		List<Serializable> choiceContent = simpleChoice.getContent();
371 		for (Serializable serializable : choiceContent) {
372 			if (serializable instanceof String) {
373 					String choice = (String) serializable;
374 					if( choice != null ) {
375 						return StringUtils.trimToNull(choice);
376 					} else {
377 						return null;
378 					}// if
379 					
380 			}// if
381 		}//for
382 		
383 	
384 		return "";
385 	
386 	}
387 
388 	protected void modButton(JButton button) {
389 		button.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 0));
390 		button.setOpaque(false);
391 		button.setBorderPainted(false);
392 		button.setFocusPainted(false); 
393 		button.setRequestFocusEnabled(false); 
394 		button.setContentAreaFilled(false);
395 	}
396 	
397 	private JPanel createButtonPanel() {
398 
399 		JPanel buttonPanel = new JPanel();
400 
401 		GridLayout gl = new GridLayout(1, 2);
402 		gl.setHgap(2);
403 		gl.setVgap(2);
404 
405 		buttonPanel.setOpaque(false);
406 		addButton = new JButton();
407 		addButton.setAction(addChoiceAction);
408 //		CommonUI.addButtonRollover(addButton, ToolIconProvider
409 //				.getImageIcon("addIconSelected.png"));
410 
411 		this.modButton(addButton);
412 		deleteButton = new JButton();
413 		deleteButton.setAction(deleteChoiceAction);
414 //		CommonUI.addButtonRollover(deleteButton,
415 //				ToolIconProvider.getImageIcon("deleteIconSelected.png"));
416 
417 		this.modButton(deleteButton);
418 		buttonPanel.add(deleteButton);
419 		buttonPanel.add(addButton);
420 
421 		return buttonPanel;
422 	}
423 
424 	final Action deleteChoiceAction = new AbstractAction(null, ToolIconProvider
425 			.getImageIcon("deleteIcon.png")) {
426 
427 		public void actionPerformed(ActionEvent e) {
428 			choiceContainerUI.trashCard(ChoiceCardUI.this);
429 		}
430 	};
431 
432 	final Action addChoiceAction = new AbstractAction(null, ToolIconProvider
433 			.getImageIcon("addIcon.png")) {
434 		public void actionPerformed(ActionEvent e) {
435 			choiceContainerUI.addNewChoice(ChoiceCardUI.this);
436 		}
437 	};
438 
439 	public ChoiceCardUI getInstance() {
440 		return this;
441 	}
442 
443 	private ChoiceCardContainerUI choiceContainerUI;
444 
445 	public static void main(String[] args) {
446 //		JFrame frame = new JFrame("note card choice test");
447 //
448 //		Container contentPane = frame.getContentPane();
449 //
450 //		JButton showButton = new JButton("show ui");
451 //
452 //		showButton.addActionListener(new ActionListener() {
453 //
454 //			public void actionPerformed(ActionEvent e) {
455 //
456 //				JFrame frame = new JFrame("card choice test");
457 //
458 //				Container contentPane = frame.getContentPane();
459 //				ChoiceCardUI noteUI = new ChoiceCardUI(null);
460 //				contentPane.add(noteUI);
461 //				frame.setSize(noteUI.getPreferredSize());
462 //				frame.setVisible(true);
463 //			}
464 //
465 //		});
466 //		contentPane.add(showButton);
467 //
468 //		frame.setSize(200, 200);
469 //		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
470 //		frame.setVisible(true);
471 	}
472 
473 	/***
474 	 * @param containerUI
475 	 */
476 	public void setChoiceContainer(ChoiceCardContainerUI choiceContainerUI) {
477 		this.choiceContainerUI = choiceContainerUI;
478 
479 	}
480 
481 	/***
482 	 * Checks if there is inline feedback. if so returns it
483 	 * 
484 	 * @return
485 	 */
486 	protected FeedbackInlineType isInlineFeedback() {
487 
488 		List<Serializable> choiceContent = simpleChoice.getContent();
489 		for (Serializable serializable : choiceContent) {
490 			if( serializable instanceof JAXBElement) {
491 				JAXBElement<FeedbackInlineType> jaxbElement = (JAXBElement<FeedbackInlineType>) serializable;
492 				Object contentItem = jaxbElement.getValue();
493 				if (contentItem instanceof FeedbackInlineType) {
494 					FeedbackInlineType inlineFeedback = (FeedbackInlineType) contentItem;
495 					return inlineFeedback;
496 				}
497 			}
498 		}//for
499 		
500 		return null;
501 	}
502 	
503 	public int getChoiceNumber() {
504 		return choiceNumber;
505 	}
506 
507 	public boolean isNeedsHeader() {
508 		return needsHeader;
509 	}
510 
511 	public void setNeedsHeader(boolean needsHeader) {
512 		this.needsHeader = needsHeader;
513 	}
514 
515 	public JRadioButton getCorrectAnswerRadio() {
516 		return correctAnswerRadio;
517 	}
518 
519 	public void setCorrectAnswerRadio(JRadioButton correctAnswerRadio) {
520 		this.correctAnswerRadio = correctAnswerRadio;
521 	}
522 
523 	public SimpleChoiceType getSimpleChoice() {
524 		return simpleChoice;
525 	}
526 
527 	public void setSimpleChoice(SimpleChoiceType simpleChoice) {
528 		this.simpleChoice = simpleChoice;
529 	}
530 
531 }