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
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
143 formPanel.add(createInputRow(),"growx");
144
145 formPanel.setOpaque(false);
146
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
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 }
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
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
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
221 if(feedbackContent.size() > 0) {
222
223 inlineFeedbackItem.getContent().remove(0);
224 }
225
226
227 inlineFeedbackItem.getContent().add(0, text);
228 }
229 }
230 }
231
232
233
234 }
235
236
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
251
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
259
260
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
294
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
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
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 }
333
334 }
335
336 }
337 sc.getContent().add(text);
338
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
347
348
349
350
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 }
379
380 }
381 }
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
409
410
411 this.modButton(addButton);
412 deleteButton = new JButton();
413 deleteButton.setAction(deleteChoiceAction);
414
415
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
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
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 }
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 }