1 /***
2 * Created on Jan 6, 2006, Copyright UC Regents
3 */
4 package org.telscenter.pas.steps.quickEditors.qti.assessment;
5
6 import java.awt.BorderLayout;
7 import java.awt.Color;
8 import java.awt.Container;
9 import java.awt.Dimension;
10 import java.awt.FlowLayout;
11 import java.awt.event.ActionEvent;
12 import java.awt.event.ActionListener;
13 import java.awt.event.FocusEvent;
14 import java.awt.event.FocusListener;
15 import java.util.ArrayList;
16 import java.util.List;
17
18 import javax.swing.BorderFactory;
19 import javax.swing.JButton;
20 import javax.swing.JCheckBox;
21 import javax.swing.JFrame;
22 import javax.swing.JLabel;
23 import javax.swing.JPanel;
24 import javax.swing.JScrollPane;
25 import javax.swing.JTextArea;
26 import javax.swing.border.CompoundBorder;
27 import javax.swing.undo.UndoManager;
28
29 import net.miginfocom.swing.MigLayout;
30 import net.sf.sail.jaxb.extension.BlockInteractionType;
31 import net.sf.sail.jaxb.extension.JaxbQtiMarshallingUtils;
32
33 import org.apache.commons.lang.StringUtils;
34 import org.imsglobal.xsd.imsqti_v2p0.AssessmentItemType;
35 import org.imsglobal.xsd.imsqti_v2p0.ItemBodyType;
36 import org.imsglobal.xsd.imsqti_v2p0.ObjectFactory;
37 import org.imsglobal.xsd.imsqti_v2p0.ResponseDeclarationType;
38 import org.telscenter.pas.common.ui.CommonUI;
39 import org.telscenter.pas.common.ui.panel.TextEditorPanel;
40 import org.telscenter.pas.steps.IAssessmentType;
41 import org.telscenter.pas.steps.IntroductionHtmlAware;
42 import org.telscenter.pas.steps.JaxbQtiNote;
43 import org.telscenter.pas.steps.JaxbQtiSelfAssessment;
44 import org.telscenter.pas.steps.JaxbQtiStep;
45 import org.telscenter.pas.steps.quickEditors.IQuickEditorControllable;
46 import org.telscenter.pas.ui.util.PasColors;
47 import org.telscenter.pas.util.JaxbQtiCreationUtils;
48
49 import com.jgoodies.binding.beans.BeanAdapter;
50
51 /***
52 * @author aperritano
53 *
54 */
55 public class AssessmentQuickEditorUI extends JPanel implements IQuickEditorControllable, FocusListener {
56
57
58 private static ObjectFactory jaxbFactory;
59 private AssessmentItemType assessmentItem = null;
60 private InteractionCardContainerUI interactionCardContainerUI;
61
62 private BeanAdapter beanAdapter;
63
64 private List<ResponseDeclarationType> responseDeclarations = new ArrayList<ResponseDeclarationType>();
65 private JScrollPane listScroller;
66
67 private JPanel buttonPanel;
68 private JaxbQtiStep assmtBean;
69 private UndoManager undoManager;
70
71
72 private int rimIndex = 0;
73 /***
74 * @param assessmentBean
75 * @param note
76 */
77 public AssessmentQuickEditorUI(JaxbQtiStep assessmentBean) {
78 super();
79 this.assmtBean = assessmentBean;
80 assessmentItem = assessmentBean.getAssessmentItem();
81 this.init();
82 }
83
84
85 /***
86 * @param noteBean
87 * @param undoManager2
88 */
89 public AssessmentQuickEditorUI(JaxbQtiStep assessmentBean,
90 UndoManager undoManager) {
91 this.assmtBean = assessmentBean;
92 assessmentItem = assessmentBean.getAssessmentItem();
93 this.undoManager = undoManager;
94 this.init();
95
96
97 }
98
99
100 /***
101 * This creates the button panel where you can add new interactions(text, choice)
102 *
103 * @return
104 */
105 protected JPanel createButtonPanel() {
106 buttonPanel = new JPanel(new FlowLayout(FlowLayout.CENTER));
107
108 String label = "";
109
110 if( ((IAssessmentType)assmtBean).hasCorrectAnswer() ) {
111 label = "Add a Multi Choice Question";
112 } else {
113 label = "Add a Survey Question";
114 }
115 JButton addMultiChoiceItem = new JButton(label);
116
117
118 buttonPanel.add(addMultiChoiceItem);
119
120 addMultiChoiceItem.addActionListener(new ActionListener() {
121
122 public void actionPerformed(ActionEvent e) {
123
124
125 BlockInteractionType bi = JaxbQtiCreationUtils.addJaxbBlockInteraction(assmtBean,CardConstants.CHOICE_ASSMT, rimIndex++, responseDeclarations);
126 AbstractCardUI inCard;
127
128
129
130 if(assmtBean.hasInlineFeedback()) {
131 bi.setHasInlineFeedback(true);
132 }
133
134 inCard = new InteractionCardUI(assmtBean, bi, assessmentItem.getResponseDeclaration(), beanAdapter, undoManager);
135
136 interactionCardContainerUI.addInteractionCard(inCard, true);
137 listScroller.getVerticalScrollBar().setValue(
138 listScroller.getVerticalScrollBar().getMaximum());
139
140 AssessmentQuickEditorUI.this.revalidate();
141 }
142 });
143
144 JButton addTextItem = new JButton("Add an Open-Response Question");
145
146 addTextItem.addActionListener(new ActionListener() {
147
148 public void actionPerformed(ActionEvent e) {
149
150
151
152 BlockInteractionType bi = JaxbQtiCreationUtils.addJaxbBlockInteraction(assmtBean,CardConstants.TEXT_ASSMT, rimIndex++, responseDeclarations);
153
154 AbstractCardUI innyCard;
155
156 innyCard = new InteractionCardUI(assmtBean, bi,assessmentItem.getResponseDeclaration(), beanAdapter, undoManager);
157
158 interactionCardContainerUI.addInteractionCard(innyCard, true);
159 listScroller.getVerticalScrollBar().setValue(
160 listScroller.getVerticalScrollBar().getMaximum());
161
162 AssessmentQuickEditorUI.this.revalidate();
163
164 }
165 });
166
167
168
169
170 if(!assmtBean.getType().equals(JaxbQtiSelfAssessment.TYPE)) {
171 buttonPanel.add(addTextItem);
172 }
173
174 buttonPanel.setOpaque(false);
175 return buttonPanel;
176 }
177
178 /***
179 * @return
180 */
181 protected JPanel createLockStudentAnswers() {
182 JPanel lockPanel = new JPanel(new BorderLayout(0,0));
183
184 JCheckBox lockBox = new JCheckBox("Lock Student Answers - When selected, student can only answer once");
185 lockBox.setSelected(assmtBean.isLockStudentAnswers());
186 lockBox.setOpaque(false);
187 lockBox.addActionListener(new ActionListener(){
188
189 public void actionPerformed(ActionEvent e) {
190 JCheckBox source = (JCheckBox) e.getSource();
191 assmtBean.setLockStudentAnswers(source.isSelected());
192 System.out.println("isLocked " + source.isSelected());
193 }});
194
195
196
197
198
199 lockBox.setBorder(BorderFactory.createEmptyBorder(4, 4, 4, 4));
200
201 lockPanel.add(lockBox, BorderLayout.WEST);
202 lockPanel.setOpaque(false);
203 return lockPanel;
204 }
205
206 /***
207 * This is a layout with no assessment interactions
208 */
209 private void createNullLayout() {
210 setLayout(new BorderLayout(0, 0));
211 setBackground(PasColors.qtiAssessmentQuickEditorBackgroundColor);
212
213 JLabel messageLabel = new JLabel("This assessment has zero items.");
214 messageLabel.setOpaque(false);
215 JPanel panel = new JPanel(new FlowLayout(FlowLayout.CENTER));
216 panel.setBorder(BorderFactory.createEmptyBorder(4, 4, 0, 4));
217 panel.add(messageLabel);
218 panel.setOpaque(false);
219
220 add(panel, BorderLayout.CENTER);
221 }
222
223 /***
224 * This is the basic UI methods, runs through the list of interactions and creates their authoring cards
225 */
226 protected void createUI() {
227 setLayout(new BorderLayout(0, 0));
228 setBackground(PasColors.qtiAssessmentQuickEditorBackgroundColor);
229
230 JPanel overAllPanel = new JPanel(new BorderLayout(0,0));
231 overAllPanel.setBackground(this.getBackground());
232
233 JPanel htmlPanel = new JPanel(new MigLayout("wrap 1, insets 0"));
234 htmlPanel.setBackground(this.getBackground());
235 htmlPanel.setOpaque(false);
236
237
238 if( assmtBean instanceof IntroductionHtmlAware) {
239 String introductionHtml = ((IntroductionHtmlAware) assmtBean).getIntroductionHtml();
240 if( introductionHtml != null)
241 htmlPanel.add(createHTMLIntroArea(StringUtils.stripToEmpty(introductionHtml)));
242 else
243 htmlPanel.add(createHTMLIntroArea(""));
244
245 }
246
247 boolean canLockAnswers = ((IAssessmentType)assmtBean).canLockAnswers();
248 if( canLockAnswers) {
249 htmlPanel.add(createLockStudentAnswers());
250 }
251
252 overAllPanel.add(htmlPanel, BorderLayout.NORTH);
253 interactionCardContainerUI = new InteractionCardContainerUI(
254 this.assessmentItem);
255 if (this.assessmentItem == null
256 || this.assessmentItem.getItemBody().getBlockElementGroup().size() == 0) {
257
258 AbstractCardUI<BlockInteractionType> nc = new InteractionCardUI(null,null, null, beanAdapter, undoManager);
259
260 } else {
261 List<Object> interactions = this.assessmentItem.getItemBody().getBlockElementGroup();
262 for (Object interaction : interactions) {
263 AbstractCardUI nc = new InteractionCardUI(assmtBean,(BlockInteractionType) interaction, assessmentItem.getResponseDeclaration(), undoManager);
264 interactionCardContainerUI.addInteractionCard(nc);
265
266
267
268 if(assmtBean.hasInlineFeedback()) {
269 ((BlockInteractionType) interaction).setHasInlineFeedback(true);
270 }
271 }
272 }
273
274 overAllPanel.add(interactionCardContainerUI,BorderLayout.CENTER);
275
276 listScroller = new JScrollPane();
277 listScroller.getViewport().add(overAllPanel);
278 listScroller
279 .setBackground(PasColors.qtiAssessmentQuickEditorListScrollerBackgroundColor);
280 listScroller
281 .setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
282 listScroller
283 .setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
284 listScroller.setBorder(BorderFactory.createEmptyBorder(0, 1, 0, 0));
285
286 JPanel scrollerPanel = new JPanel(new BorderLayout(0, 0));
287 scrollerPanel.setBorder(BorderFactory.createEmptyBorder(4, 4, 0, 4));
288 scrollerPanel.add(listScroller, BorderLayout.CENTER);
289 scrollerPanel.setOpaque(false);
290
291 JPanel bp = createButtonPanel();
292 add(scrollerPanel, BorderLayout.CENTER);
293 if( bp != null)
294 add(bp, BorderLayout.SOUTH);
295 }
296
297 /***
298 * Create HTML text area
299 *
300 * @return
301 */
302 protected JPanel createHTMLIntroArea(String html) {
303
304 String trimToNull = StringUtils.trimToNull(html);
305
306 if( trimToNull == null )
307 html = " ";
308 JTextArea htmlArea = new JTextArea(html);
309
310 TextEditorPanel ppanel = new TextEditorPanel(htmlArea,new Dimension(CardConstants.TEXT_AREA_LENTH, 125));
311 htmlArea.setBackground(ppanel.getBackground());
312 JButton jb = ppanel.getEditButton();
313 if( jb != null ) {
314 jb.addActionListener(CommonUI.createHTMLTidyEditActionlistener());
315 }
316
317 if( undoManager != null)
318 htmlArea.getDocument().addUndoableEditListener(undoManager);
319 htmlArea.addFocusListener(new FocusListener() {
320
321 public void focusGained(FocusEvent e) {}
322
323 public void focusLost(FocusEvent e) {
324 JTextArea source = (JTextArea) e.getSource();
325
326 String promptText = source.getText();
327
328 ((IntroductionHtmlAware)assmtBean).setIntroductionHtml(promptText);
329
330 }});
331
332 CompoundBorder b = BorderFactory.createCompoundBorder(BorderFactory.createEmptyBorder(2, 2, 2, 2), BorderFactory.createTitledBorder(BorderFactory.createLineBorder(Color.WHITE), "Introduction Text"));
333
334 ppanel.setBorder(b);
335 ppanel.setOpaque(false);
336
337 return ppanel;
338 }
339
340 /***
341 * Get the assessmentItem
342 *
343 * @return
344 */
345 public AssessmentItemType getAssessmentItem() {
346 return assessmentItem;
347 }
348
349 /***
350 * Set the assessmentItem
351 *
352 * @param item
353 */
354 public void setAssessmentItem(AssessmentItemType assessmentItem) {
355 if (assessmentItem == null) {
356 createUI();
357 } else {
358 this.assessmentItem = assessmentItem;
359
360 removeAll();
361 createUI();
362 }
363 }
364
365
366
367 /***
368 * Initialize the interface.
369 *
370 * @param item
371 */
372 public void init() {
373 if (assessmentItem == null) {
374 assessmentItem = JaxbQtiMarshallingUtils.getJaxbObjectFactory().createAssessmentItemType();
375
376 ItemBodyType itemBody = JaxbQtiMarshallingUtils.getJaxbObjectFactory().createItemBodyType();
377 assessmentItem.setItemBody(itemBody);
378
379 List<BlockInteractionType> interactions = new ArrayList<BlockInteractionType>();
380
381
382
383
384 assmtBean.setAssessmentItem(assessmentItem);
385 if( assmtBean instanceof IntroductionHtmlAware) {
386 ((IntroductionHtmlAware) assmtBean).setIntroductionHtml(CardConstants.htmlStartTag + CardConstants.DEFAULT_INTRODUCTION_HTML + CardConstants.htmlEndTag);
387
388 }
389 createUI();
390 } else {
391 removeAll();
392 createUI();
393 }
394 }
395
396
397
398 /***
399 * basic event for focus
400 *
401 * @see java.awt.event.FocusListener#focusGained(java.awt.event.FocusEvent)
402 */
403 public void focusGained(FocusEvent e) {
404 System.out.println("QTIAssessmentQuickEditorUI.focusGained()");
405 }
406
407 /***
408 * Basic event for focus
409 *
410 * @see java.awt.event.FocusListener#focusLost(java.awt.event.FocusEvent)
411 */
412 public void focusLost(FocusEvent e) {
413 System.out.println("QTIAssessmentQuickEditorUI.focusLost()");
414 }
415
416 /***
417 *
418 * Basic Event for focus
419 *
420 * @see org.telscenter.pas.steps.quickEditors.IQuickEditorControllable#getControllPanel()
421 */
422 public JPanel getControllPanel() {
423 return buttonPanel;
424 }
425
426 /***
427 * Tester method
428 *
429 * @param args
430 */
431 public static void main(String[] args) {
432 JFrame frame = new JFrame("note quick editor test");
433
434 Container contentPane = frame.getContentPane();
435
436 JButton showButton = new JButton("show ui");
437
438 showButton.addActionListener(new ActionListener() {
439
440 public void actionPerformed(ActionEvent e) {
441
442 JFrame frame = new JFrame("note quick editor test");
443
444 Container contentPane = frame.getContentPane();
445 AssessmentQuickEditorUI noteUI = new AssessmentQuickEditorUI(null);
446 noteUI.setAssessmentItem(new AssessmentItemType());
447 contentPane.add(noteUI);
448 frame.setSize(noteUI.getPreferredSize());
449 frame.setVisible(true);
450 }
451
452 });
453 contentPane.add(showButton);
454
455 frame.setSize(200, 200);
456 frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
457 frame.setVisible(true);
458 }
459
460
461
462
463 public UndoManager getUndoManager() {
464 return undoManager;
465 }
466
467
468
469
470 public void setUndoManager(UndoManager undoManager) {
471 this.undoManager = undoManager;
472 }
473
474 }