View Javadoc

1   /*
2    * Created on Apr 27, 2005, Copyright UC Regents
3    */
4   package org.telscenter.pas.steps;
5   
6   import java.awt.BorderLayout;
7   import java.awt.Color;
8   import java.awt.Component;
9   import java.awt.Container;
10  import java.awt.Dimension;
11  import java.awt.FlowLayout;
12  import java.awt.Font;
13  import java.awt.GridBagConstraints;
14  import java.awt.GridBagLayout;
15  import java.awt.Point;
16  import java.awt.event.ActionEvent;
17  import java.awt.print.PrinterException;
18  import java.awt.print.PrinterJob;
19  import java.text.DecimalFormat;
20  import java.util.HashMap;
21  import java.util.List;
22  import java.util.Map;
23  import java.util.logging.Logger;
24  
25  import javax.swing.AbstractAction;
26  import javax.swing.BorderFactory;
27  import javax.swing.BoxLayout;
28  import javax.swing.ImageIcon;
29  import javax.swing.JButton;
30  import javax.swing.JComponent;
31  import javax.swing.JLabel;
32  import javax.swing.JPanel;
33  import javax.swing.JProgressBar;
34  import javax.swing.JScrollPane;
35  import javax.swing.JTextArea;
36  import javax.swing.JTextField;
37  import javax.swing.SwingUtilities;
38  import javax.swing.border.Border;
39  import javax.swing.border.TitledBorder;
40  
41  import net.miginfocom.swing.MigLayout;
42  import net.sf.sail.core.beans.Pod;
43  import net.sf.sail.core.beans.service.AnnotationService;
44  import net.sf.sail.core.entity.AgentSet;
45  import net.sf.sail.core.entity.IAgent;
46  import net.sf.sail.core.entity.IAnnotation;
47  import net.sf.sail.core.entity.MismatchedAgentSetSizeException;
48  import net.sf.sail.core.entity.Rim;
49  import net.sf.sail.core.entity.Role;
50  import net.sf.sail.core.entity.User;
51  
52  import org.apache.commons.lang.StringUtils;
53  import org.telscenter.pas.beans.IWorkReporter;
54  import org.telscenter.pas.beans.PasActivity;
55  import org.telscenter.pas.beans.PasProject;
56  import org.telscenter.pas.beans.PasStep;
57  import org.telscenter.pas.common.ui.CommonUI;
58  import org.telscenter.pas.common.ui.panel.SimpleGradientPanel;
59  import org.telscenter.pas.navigation.PasProjectNavigationTaskPanel;
60  import org.telscenter.pas.service.INavigationService;
61  import org.telscenter.pas.service.NavigateAction;
62  import org.telscenter.pas.service.PasProjectServiceProvider;
63  import org.telscenter.pas.steps.domain.AssessmentItem;
64  import org.telscenter.pas.steps.domain.ResponseDeclaration;
65  import org.telscenter.pas.ui.frames.PasFrame;
66  import org.telscenter.pas.ui.icons.PasCommonIconProvider;
67  import org.telscenter.pas.ui.pdf.actions.GeneratePDFAction;
68  import org.telscenter.pas.ui.util.PasColors;
69  import org.telscenter.pas.util.AnnotationUtils;
70  
71  //import com.lowagie.text.pdf.PdfPCell;
72  
73  /***
74   * A generic Pas step type, used for testing and demonstration purposes.
75   * This PasStep does not get initialized like the other Pas steps, 
76   * so consumeService cannot be used.
77   * 
78   * @author turadg
79   */
80  public class ShowAllWorkStep extends PasStep  {
81  
82  	/***
83  	 * 
84  	 */
85  	private static final String UNSCORED = "unscored";
86  
87  	private static final long serialVersionUID = 1L;
88  	
89  	PasProjectServiceProvider provider;
90  	PasProject project;
91  	INavigationService navigationService;
92  	AnnotationService annotationService;
93  	boolean visited = false;
94  	private boolean withAnnotations = false;
95  
96  	private PasProjectNavigationTaskPanel projectNavigationTaskPanel;
97  
98  	private static final int STUDENTWORK_MAX_SIZE_X = 250;
99  	private static final int STUDENTWORK_MAX_SIZE_Y = 150;
100 	private static final int TEACHERCOMMENTS_MAX_SIZE_X = 10;
101 	private static final int TEACHERCOMMENTS_MAX_SIZE_Y = 10;
102 	private static final int SCORE_MAX_SIZE_X = 70;
103 	private static final int SCORE_MAX_SIZE_Y = 80;
104 	
105 	private static final Logger logger = Logger
106 	.getLogger(ShowAllWorkStep.class.getName());
107 	
108 	private JProgressBar percentageCompleteBar = new JProgressBar(0, 100);
109 
110 	private JLabel currentScoreEquationLabel = new JLabel();
111 
112 	private HashMap<PasStep,String> stepsToTeacherScores = new HashMap<PasStep, String>();
113 	
114 	private HashMap<PasStep,String> stepsToPossibleScores = new HashMap<PasStep, String>();
115 	
116 	
117 	public ShowAllWorkStep(PasProject project, INavigationService navigationService){
118 		this.project = project;
119 		this.navigationService = navigationService;
120 		this.annotationService = project.getAnnotationService();
121 		if(annotationService != null && annotationService.isAvailable()){
122 			withAnnotations = true;
123 		}
124 	}
125 	
126 	public Component getComponent() {
127 		PasActivity[] activities = project.getActivities();
128 		 projectNavigationTaskPanel = project.getPanel();
129 		JPanel activitiesPanel = traverseActivities(activities, projectNavigationTaskPanel);		
130 		final JScrollPane scrollPane = setScrollPane(activitiesPanel);
131 		JPanel titleAndButtonPanel = createTitleAndButtonPanel();
132 		JPanel mainShowAllWorkPanel = setMainShowAllWorkPanel(titleAndButtonPanel, scrollPane);
133 		setStepTitlePanelVisited(true);
134 		
135 		return mainShowAllWorkPanel;
136 	}
137 	
138 	private class PrintAllWorkAction extends AbstractAction {
139 		
140 		public PrintAllWorkAction(String title){
141 			super(title);
142 		}
143 		
144 		public void runAction() {
145 			SwingUtilities.invokeLater(new Runnable() {
146 				public void run() {
147 					openPrintDialog();
148 				}
149 			});
150 		}
151 		
152 		public void openPrintDialog(){
153 			  PrinterJob printJob = PrinterJob.getPrinterJob();
154 		//	    printJob.setPrintable(new Printable());
155 			    if (printJob.printDialog())
156 			      try { 
157 			        printJob.print();
158 			      } catch(PrinterException pe) {
159 			        System.out.println("Error printing: " + pe);
160 			      }
161 			
162 		}
163 		
164 		public void actionPerformed(ActionEvent e) {
165 			this.runAction();
166 		}
167 		
168 	}
169 
170 /******************************************************************************************/	
171 /********************** TRAVERSING ACTIVITIES AND STEPS ***********************************/	
172 	
173 	
174 	/***
175 	 * goes through all the activities, grabbing the title for each activity, setting the activity title panel, and 
176 	 * adding all the corresponding IWorkReporter steps with student work, teacher comments (annotations), and score, 
177 	 * in each activity (assuming that the activity has at least one step), 
178 	 * with each step split up into its parts. A check is initially done to see whether there are any annotations: if 
179 	 * there are no annotations, only the student work is shown; otherwise, the student work, teacher comments, and scores
180 	 * are shown.
181 	 * 
182 	 *  
183 	 * @param activities
184 	 * @param thisPanel
185 	 * @return activitiesPanel
186 	 */
187 	private JPanel traverseActivities(PasActivity[] activities, PasProjectNavigationTaskPanel thisPanel) {
188 		float headerFontSize = 16.0f;
189 		JPanel activitiesPanel = new JPanel(new BorderLayout(0,0));
190 		//activitiesPanel.setLayout(new BoxLayout(activitiesPanel, BoxLayout.Y_AXIS));
191 
192 		MigLayout mig = new MigLayout("insets 0 0 0 0");
193 		activitiesPanel.setLayout(mig);
194 		activitiesPanel.setBackground(PasColors.showReportsActivityBackgroundColor);
195 		//activitiesPanel.setBackground(Color.red);
196 		
197 		for (int i = 0; i < activities.length; i++) {
198 			PasActivity activity = activities[i];
199 			JLabel actTitle = getActivityTitle(i, activity);
200 			JPanel titlePanel = getActTitlePanel(actTitle);
201 			
202 			JPanel activityPanel = new JPanel(new BorderLayout(0,0));
203 			activityPanel.setBackground(PasColors.showReportsActivityBackgroundColor);
204 			
205 			//activityPanel.setBackground(Color.red);
206 			activityPanel.add(titlePanel, BorderLayout.NORTH);
207 				
208 				
209 				
210 				//setActivityPanel(titlePanel);
211 			//JLabel myWorkLabel = new JLabel("My Work");
212 //			myWorkLabel.setFont(myWorkLabel.getFont().deriveFont(Font.BOLD, headerFontSize));
213 
214 			if( activity.getSteps().length > 0) {
215 				PasStep[] steps = activity.getSteps();
216 				JPanel stepsPanel = new JPanel();
217 				
218 				MigLayout mig1 = new MigLayout("insets 0 0 0 0");
219 				stepsPanel.setLayout(mig1);
220 				
221 				if (withAnnotations) {
222 					//stepsPanel.setLayout(new BoxLayout(stepsPanel, BoxLayout.Y_AXIS));
223 					//stepsPanel.add(myWorkLabel, BorderLayout.WEST);
224 					stepsPanel = traverseSteps(thisPanel, steps);
225 				} else {
226 					//stepsPanel.setLayout(new BoxLayout(stepsPanel, BoxLayout.Y_AXIS));
227 					//stepsPanel.add(myWorkLabel, BorderLayout.WEST);
228 					
229 					int iterator = 0;
230 
231 					for (final PasStep step: steps) {
232 						if (step instanceof IWorkReporter) {
233 							JButton stepTitle = createStepTitleButton(thisPanel, iterator, step);
234 							JPanel stepTitlePanel = new JPanel(new BorderLayout(0,0));
235 							stepTitlePanel.add(CommonUI.makeLink(stepTitle),BorderLayout.WEST);
236 							stepTitlePanel.setBackground(PasColors.showReportsActivityBackgroundColor);
237 							stepsPanel.add(stepTitlePanel,"wrap");
238 							
239 							NavigateAction navigateAction = null;
240 							JPanel reportForLearner;
241 							
242 							//assessment is special
243 							if( step instanceof StudentAssessment || step instanceof Note) {
244 								navigateAction = new NavigateAction(step, navigationService,projectNavigationTaskPanel);
245 								reportForLearner = ((IWorkReporter) step).getReportForLearner(navigateAction);
246 							} else {
247 								reportForLearner = ((IWorkReporter) step).getReportForLearner();
248 							}
249 							
250 							stepsPanel.add(reportForLearner,"wrap");
251 							stepsPanel.setBackground(PasColors.showReportsActivityBackgroundColor);
252 							
253 						}
254 						iterator++;
255 				}
256 					
257 				}
258 				
259 				activityPanel.add(stepsPanel,BorderLayout.WEST);
260 				activitiesPanel.add(activityPanel,"wrap");					
261 			}	
262 		}
263 		
264 		//process scores
265 		
266 		//create progressbar
267 		if(withAnnotations) {
268 		
269 			int numberOfGradedSteps = 0;
270 			int totalTeacherScore = 0;
271 			int totalPossibleScore = 0;
272 			for (Map.Entry<PasStep, String> entries : stepsToTeacherScores.entrySet()) {
273 				
274 				PasStep pasStep = entries.getKey();
275 				String score = entries.getValue();
276 				
277 				if( !score.equals(UNSCORED)) {
278 					 numberOfGradedSteps++;
279 					
280 					if( StringUtils.isNumeric(score)) {
281 						totalTeacherScore = totalTeacherScore + new Integer(score).intValue();
282 						
283 						String possibleScore = stepsToPossibleScores.get(pasStep);
284 						
285 						totalPossibleScore = totalPossibleScore + new Integer(possibleScore).intValue();
286 					}
287 				}
288 			}// for
289 			
290 			
291 			String pattern = "###";
292 			DecimalFormat myFormatter = new DecimalFormat(pattern);
293 			
294 			int numberGradableSteps = stepsToPossibleScores.keySet().size();
295 			
296 			//compute raw score percent
297 			double percentGrade = (((double)totalTeacherScore)/((double)totalPossibleScore)) * 100;
298 			
299 			String perValue = myFormatter.format(percentGrade);
300 			
301 			
302 			//compute raw score
303 			currentScoreEquationLabel.setText(totalTeacherScore+"/"+totalPossibleScore+" = " + perValue+ "%");
304 			currentScoreEquationLabel.revalidate();
305 
306 			
307 			
308 			//compute percentage completed
309 			if( numberGradableSteps != 0 ) {
310 				
311 				double percentCompleted = (((double)numberOfGradedSteps)/((double)numberGradableSteps)) * 100;
312 				
313 				
314 				String value = myFormatter.format(percentCompleted);
315 				
316 				percentageCompleteBar.setValue(new Integer(value));
317 			}
318 			//
319 			
320 			
321 		}// if
322 		
323 		return activitiesPanel;
324 	}
325 
326 	/***
327 	 * visits all the steps in the current activity, checking to see that if a step is an instance of 
328 	 * IWorkReporter, initialize its step parts listing, and creates a step panel to return, including the
329 	 * step title and corresponding parts (with student answers)
330 	 *  
331 	 * @param thisPanel
332 	 * @param steps
333 	 * @return stepsPanel
334 	 */
335 	private JPanel traverseSteps(PasProjectNavigationTaskPanel thisPanel, PasStep[] steps) {
336 		JPanel stepsPanel = new JPanel();
337 		MigLayout mig = new MigLayout( "insets 0 0 0 0");
338 		stepsPanel.setLayout(mig);
339 		stepsPanel.setBackground(PasColors.showReportsActivityBackgroundColor);
340 		//stepsPanel.setLayout(new BoxLayout(stepsPanel, BoxLayout.Y_AXIS));
341 		
342 		for (int j = 0; j < steps.length; j++) {
343 			PasStep step = steps[j];
344 			
345 			if (step instanceof IWorkReporter) {
346 				((IWorkReporter) step).initStepParts();
347 				JButton stepTitleButton = createStepTitleButton(thisPanel, j, step);
348 
349 				JPanel stepTitlePanel = new JPanel(new BorderLayout(0,0));
350 				stepTitlePanel.add(CommonUI.makeLink(stepTitleButton),BorderLayout.WEST);
351 			    stepTitlePanel.setOpaque(false);
352 				JPanel stepPanel = createStepPanel(step);
353 				// stepContentPanel includes studentwork, teacher comments and score
354 				
355 				//stepPanel.setBorder(BorderFactory.createEtchedBorder(46));
356 				stepsPanel.add(stepTitlePanel,"wrap");				
357 				stepsPanel.add(stepPanel,"wrap");
358 			
359 				stepsPanel.setBorder(BorderFactory.createEmptyBorder(0, 8, 8, 10));
360 				stepsPanel.setOpaque(true);
361 				
362 			}// if
363 		}// for
364 		
365 		return stepsPanel;
366 	}
367 
368 /******************************************************************************************/	
369 /******************************************************************************************/	
370 /*********************************************  TITLE PANELS ******************************/
371 	/*
372 	 * createTitleAndButtonPanel
373 	 * getActTitlePanel
374 	 * setActivityPanel
375 	 * setScrollPane
376 	 * setMainShowAllWorkPanel
377 	 */
378 	
379 	/***
380 	 * creates title for show all work and the corresponding function buttons, to print, save, and email 
381 	 * the work for students
382 	 * TODO: PDF functionality 
383 	 * @return titleAndButtonPanel
384 	 */
385 	
386 	private JPanel createTitleAndButtonPanel(){
387 		float headerFontSize=28.0f;
388 		JLabel showAllWorkLabel = new JLabel("SHOW ALL WORK");
389 		showAllWorkLabel.setFont(showAllWorkLabel.getFont().deriveFont(Font.BOLD, headerFontSize));
390 		showAllWorkLabel.setForeground(new Color(202,225,255));
391 
392 		SimpleGradientPanel showAllWorkPanel = createSimpleGradientPanel();
393 		GridBagConstraints c = createGridBagConstraint();
394 		showAllWorkPanel.add(showAllWorkLabel, c);
395 		
396 		JButton printAllWork = new JButton(new PrintAllWorkAction("Print All Work"));
397 		printAllWork.setText("Print All Work");
398 		printAllWork.setForeground(new Color(202,225,255));
399 		printAllWork.setContentAreaFilled(false);		
400 		printAllWork.setBorder(BorderFactory.createEmptyBorder(0, 0, 8, 0));					
401 		
402 		JButton saveAsPdfFile = new JButton(new GeneratePDFAction(new ImageIcon( PasCommonIconProvider.getImage("pdf.png") ), "Make PDF",project));
403 		saveAsPdfFile.setText("Save As PDF File");
404 		saveAsPdfFile.setForeground(new Color(202,225,255));
405 		saveAsPdfFile.setContentAreaFilled(false);		
406 		saveAsPdfFile.setBorder(BorderFactory.createEmptyBorder(0, 0, 8, 0));					
407 
408 		JButton emailPdfFile = new JButton("Email PDF File");
409 		emailPdfFile.setForeground(new Color(202,225,255));	
410 		emailPdfFile.setContentAreaFilled(false);		
411 		emailPdfFile.setBorder(BorderFactory.createEmptyBorder(0, 0, 8, 0));					
412 
413 		SimpleGradientPanel buttonPanel = createSimpleGradientPanel();
414 		c.gridx = 1;
415 		c.gridy=0;
416 		buttonPanel.add(printAllWork, c);
417 		c.gridx=2;
418 		buttonPanel.add(saveAsPdfFile,c);
419 		c.gridx=3;
420 		buttonPanel.add(emailPdfFile,c);
421 		
422 		PasFrame projectFrame = project.getProjectFrame();
423 		String userNameMessage = "BY: ";
424 		if(projectFrame != null)
425 			userNameMessage = userNameMessage.concat(projectFrame.getUserNames());
426 			
427 		SimpleGradientPanel namePanel = new SimpleGradientPanel();
428 		namePanel.add(new JLabel(userNameMessage));
429 		
430 		SimpleGradientPanel titleAndButtonPanel = createSimpleGradientPanel();
431 		c.gridx=2;
432 		c.gridy=0;
433 		titleAndButtonPanel.add(showAllWorkPanel,c);
434 		c.gridx=3;
435 		titleAndButtonPanel.add(buttonPanel,c);
436 		c.gridx=0;
437 		c.gridy=1;
438 		c.gridwidth = GridBagConstraints.WEST;
439 		titleAndButtonPanel.add(namePanel,c);
440 		return titleAndButtonPanel;		
441 	}
442 	
443 	/***
444 	 * creates a simple gradient panel for background
445 	 * 
446 	 * @return mainPanel
447 	 */
448 	private SimpleGradientPanel createSimpleGradientPanel() {
449 		SimpleGradientPanel mainPanel = new SimpleGradientPanel();
450 		mainPanel.setDirection(SimpleGradientPanel.VERTICAL);
451 		mainPanel.setStartColor(PasColors.vleHeadingBackgroundStartColor);
452 		mainPanel.setEndColor(PasColors.vleHeadingBackgroundEndColor);
453 		mainPanel.setLayout(new GridBagLayout());
454 		return mainPanel;
455 	}
456 	
457 	/***
458 	 * @return c
459 	 * creates the position of the component to be shown via grid bag layout
460 	 */
461 	private GridBagConstraints createGridBagConstraint() {
462 		GridBagConstraints c = new GridBagConstraints();
463 		c.fill = GridBagConstraints.BOTH;
464 
465 		c.weightx = 1;
466 		c.gridx = 0;
467 		c.gridy = 0;
468 	//	mainPanel.add(bannerPanel, c);
469 
470 		c.gridx = 0;
471 		c.gridy = 0;
472 		//mainPanel.add(introPanel, c);
473 
474 		c.weighty = 1;
475 		c.gridx = 0;
476 		c.gridy = 0;
477 		c.fill = GridBagConstraints.BOTH;
478 		return c;
479 	}
480 	
481 	
482 	
483 	
484 
485 	/***
486 	 * creates a big white title panel for an activity, with the activity's title aligned to the left
487 	 * 
488 	 * @param actTitle
489 	 * @return titlePanel
490 	 */
491 	private JPanel getActTitlePanel(JLabel actTitle) {
492 		JPanel titlePanel = new JPanel(new BorderLayout(0,0));
493 		titlePanel.add(actTitle,BorderLayout.WEST);
494 		
495 		//green
496 		titlePanel.setBackground(new Color(69,221,106));
497 		titlePanel.setBorder(BorderFactory.createLineBorder(PasColors.showReportsActivityTitleBorderColor, 1));
498 		
499 		JPanel wrapperPanel = new JPanel(new BorderLayout(0,0));
500 		wrapperPanel.setBorder(BorderFactory.createEmptyBorder(0, 0, 5, 0));
501 		wrapperPanel.add(titlePanel,BorderLayout.CENTER);
502 		wrapperPanel.setBackground(PasColors.showReportsActivityBackgroundColor);
503 		return wrapperPanel;
504 	}
505 
506 	/***
507 	 * creates the actual activity panel, adding the activity title panel within it
508 	 * 
509 	 * @param titlePanel
510 	 * @return activityPanel
511 	 */
512 	private JPanel setActivityPanel(JPanel titlePanel) {
513 		JPanel activityPanel;
514 		activityPanel = new JPanel(new BorderLayout());
515 		//activityPanel.setLayout(new BoxLayout(activityPanel, BoxLayout.Y_AXIS));
516 		
517 		activityPanel.setBackground(PasColors.showReportsActivityBackgroundColor);
518 		//activityPanel.add(titlePanel.Bor);
519 		return activityPanel;
520 	}
521 	
522 	
523 	/***
524 	 * creates the step panel, by visiting each and every part of the step, and adding the student part,
525 	 * teacher comments and score for that part before proceeding to the next part. note that the score part 
526 	 * is only included once per step, and therefore is not repeatedly included after the first part. instead,
527 	 * to fill up the horizontal space, a filler panel of equal size but with the background color is included.
528 	 * 
529 	 * @param step must be instance of IWorkReporter
530 	 * @return stepPanel
531 	 */
532 	private JPanel createStepPanel(PasStep step){
533 		assert step instanceof IWorkReporter;
534 		
535 		NavigateAction navigateAction = null;
536 		JPanel reportForLearner;
537 		
538 		//assessment is special
539 		if( step instanceof Assessment ) {
540 			navigateAction = new NavigateAction(step, navigationService,projectNavigationTaskPanel);
541 			reportForLearner = ((IWorkReporter) step).getReportForLearnerWithAnnotations(navigateAction);
542 		} else {
543 			reportForLearner = ((IWorkReporter) step).getReportForLearnerWithAnnotations();
544 		}
545 		
546 		//((IWorkReporter) step).getReportForLearnerWithAnnotations();  // need to call this to populate step.currentstepparts
547 		List<JPanel> theParts = ((IWorkReporter) step).getCurrentStepParts();
548 		JPanel stepPanel = initStepPanel();
549 	
550 		if (step instanceof Note || step instanceof StudentAssessment || step instanceof ChallengeQuestion) {
551 			MigLayout ml = new MigLayout("insets 0 0 0 0");
552 			JPanel columnPanel = new JPanel(ml);
553 			
554 			JPanel teacherCommentPanel = null;
555 			JPanel scorePanel = null;
556 			
557 			for(int i = 0; i < theParts.size(); i++){
558 				JPanel studentPart = theParts.get(i);
559 				
560 				studentPart.setBackground(PasColors.showReportsActivityBackgroundColor);
561 				studentPart.setBorder(BorderFactory.createCompoundBorder(createEmptyTitledBorder("Part " + (i+1), studentPart), BorderFactory.createLineBorder(Color.BLACK,1)));
562 				
563 						
564 				columnPanel.add(studentPart,"wrap");
565 				columnPanel.setBorder(BorderFactory.createEmptyBorder());
566 				columnPanel.setOpaque(false);
567 				
568 				String comments = processTheAnnotations(step, i, this.project);
569 //				//makes teachers comments
570 				teacherCommentPanel = makeTeacherCommentPanel(comments);
571 				teacherCommentPanel.setOpaque(false);
572 				scorePanel = getScorePart(step, i, this.project);
573 				scorePanel.setBackground(PasColors.showReportsActivityBackgroundColor);
574 			}// for
575 			
576 //			ml = new MigLayout(
577 //			"", 						//layout constraints		
578 //			"[][][]",			//colum constraints
579 //			"[][][]"							//row constraints
580 //			);
581 			MigLayout ml2 = new MigLayout("insets 0 0 0 0");
582 			stepPanel.setOpaque(true);
583 			stepPanel.setBackground(PasColors.showReportsActivityBackgroundColor);
584 			stepPanel.setLayout(ml2);
585 			stepPanel.add(columnPanel,"top gapleft 40");
586 			stepPanel.add(teacherCommentPanel,"top");
587 			stepPanel.add(scorePanel,"top");
588 
589 		} else {
590 			
591 			if( theParts != null ) {
592 				for(int i = 0; i < theParts.size(); i++){		
593 					JPanel stepPartPanel = new JPanel();
594 					stepPartPanel.setLayout(new BoxLayout(stepPartPanel,BoxLayout.X_AXIS));
595 					stepPartPanel.setAlignmentY(Component.TOP_ALIGNMENT);
596 	
597 					JPanel studentPart = getStudentPart(theParts, i);
598 					studentPart.setBorder(BorderFactory.createLineBorder(Color.BLACK,1));
599 					String comments = processTheAnnotations(step, i, this.project);
600 					JPanel teacherCommentsPart = makeTeacherCommentPanel(comments);
601 					teacherCommentsPart.setBorder(BorderFactory.createLineBorder(Color.BLACK,1));
602 					JPanel scorePart = getScorePart(step, i, this.project);
603 					//	scorePart.setBorder(BorderFactory.createLineBorder(Color.BLACK,1));
604 					JPanel fillerPanel = new JPanel();
605 					fillerPanel.setAlignmentY(Component.TOP_ALIGNMENT);				
606 					fillerPanel.setBackground(PasColors.showReportsContentPanelBackgroundColor);
607 					fillerPanel.setSize(SCORE_MAX_SIZE_X,  STUDENTWORK_MAX_SIZE_Y);
608 					fillerPanel.setMaximumSize(new Dimension(SCORE_MAX_SIZE_X,  STUDENTWORK_MAX_SIZE_Y));
609 					stepPartPanel.add(studentPart);
610 					stepPartPanel.add(teacherCommentsPart);
611 					if(i==0){
612 						fillerPanel.add(scorePart);
613 					}	
614 					stepPartPanel.add(fillerPanel);
615 					stepPanel.add(stepPartPanel);
616 				}  // end of for each part
617 			} else {
618 				JLabel noAnnonationLabel = new JLabel("this step has no annotations");
619 				noAnnonationLabel.setOpaque(false);
620 				stepPanel.add(noAnnonationLabel);
621 				// if
622 			}// if
623 		}
624 		return stepPanel;
625 	}
626 
627 	
628 	/***
629 	 * initializes the step panel, which is used for adding the corresponding step parts to 
630 	 * 
631 	 * @return stepPanel
632 	 */
633 	private JPanel initStepPanel() {
634 		JPanel stepPanel = new JPanel();
635 		stepPanel.setLayout(new BoxLayout(stepPanel, BoxLayout.Y_AXIS));
636 		stepPanel.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 0));		
637 		stepPanel.add(new JLabel(" "),BorderLayout.NORTH);
638 		return stepPanel;
639 	}
640 	
641 	protected static Border createEmptyTitledBorder(String title, JComponent component) {
642 		return BorderFactory.createTitledBorder(BorderFactory.createEmptyBorder(), title,TitledBorder.LEFT,TitledBorder.ABOVE_TOP,component.getFont().deriveFont(10f));
643 	}
644 
645 	/***
646 	 * returns a score panel with the score value for the corresponding step 
647 	 * 
648 	 * @return scorePanel;
649 	 */
650 	private static JPanel getScorePart(PasStep step, int rdIndex, PasProject project){
651 		JPanel scorePanel = new JPanel(new FlowLayout());
652 		
653 		
654 		scorePanel.setBorder(createEmptyTitledBorder("Score",scorePanel));
655 
656 		String score = processScore(step, rdIndex, project);
657 		
658 		if( score == null || StringUtils.trimToNull(score) == null ) {
659 			score = UNSCORED;
660 		}
661 		
662 		
663 		//stepsToTeacherScores.put(step, score);
664 		
665 		JTextField teacherScoreField = new JTextField(score);
666 		teacherScoreField.setColumns(5);
667 		teacherScoreField.setHorizontalAlignment(JTextField.CENTER);
668 		teacherScoreField.setEditable(false);
669 		teacherScoreField.setBorder(BorderFactory.createCompoundBorder(BorderFactory.createLineBorder(PasColors.blackColor,1),BorderFactory.createEmptyBorder(1,1,1,1)));
670 		
671 		Integer possibleScore = ((IWorkReporter)step).getPossibleScore();
672 		
673 		//stepsToPossibleScores.put(step, possibleScore.toString());
674 		
675 		JTextField possibleScoreField = new JTextField(possibleScore.toString());
676 		possibleScoreField.setHorizontalAlignment(JTextField.CENTER);
677 		possibleScoreField.setColumns(5);
678 		possibleScoreField.setEditable(false);
679 		possibleScoreField.setBorder(BorderFactory.createCompoundBorder(BorderFactory.createLineBorder(PasColors.blackColor,1),BorderFactory.createEmptyBorder(1,1,1,1)));
680 		
681 		JLabel ofLabel = new JLabel("of");
682 		
683 		scorePanel.add(teacherScoreField);
684 		scorePanel.add(ofLabel);
685 		scorePanel.add(possibleScoreField);
686 		scorePanel.setBackground(Color.WHITE);
687 		//scorePanel.setBorder(BorderFactory.createLineBorder(PasColors.blackColor,1));
688 		return scorePanel;
689 	}
690 	
691 
692 	/***
693 	 * puts the entire activities panel (consisting of the activities' steps and corresponding
694 	 * parts with work) into a scroll pane (after all, the entire project can easily span 
695 	 * many pages work of activities and steps so a scroll pane would be necessary)
696 	 * 
697 	 * 
698 	 * @param activitiesPanel
699 	 * @return scrollPane
700 	 */
701 	private JScrollPane setScrollPane(JPanel activitiesPanel) {
702 		final JScrollPane scrollPane = new JScrollPane(activitiesPanel,JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
703 		scrollPane.setBorder(BorderFactory.createEmptyBorder());
704 		scrollPane.setOpaque(false);
705 
706 		// workaround for scrollbar being at bottom
707 		SwingUtilities.invokeLater(new Runnable() {
708 			public void run() {
709 				scrollPane.getViewport().setViewPosition(new Point(0,0));
710 			}
711 		});
712 //		scrollPane.getHorizontalScrollBar().setVisible(false);
713 //		scrollPane.getHorizontalScrollBar().setEnabled(false);
714 		return scrollPane;
715 	}
716 	
717 	/***
718 	 * adds title and button panel (consisting of the 'show all work' and function button headings)
719 	 * and the scroll pane (consisting of the corresponding activities) inside it to return
720 	 *  
721 	 * @param titleAndButtonPanel
722 	 * @param spane
723 	 * @return mainShowAllWorkPanel
724 	 */
725 	private JPanel setMainShowAllWorkPanel(JPanel titleAndButtonPanel, final JScrollPane spane) {
726 		JPanel mainShowAllWorkPanel = new JPanel(new BorderLayout(0,0));
727 		mainShowAllWorkPanel.setOpaque(false);
728 		mainShowAllWorkPanel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
729 		
730 //		if(withAnnotations) {
731 //			//SimpleGradientPanel namePanel = new SimpleGradientPanel();
732 //			SimpleGradientPanel outerPanel = new SimpleGradientPanel(new BorderLayout(0,0));
733 //			outerPanel.setBackground(titleAndButtonPanel.getBackground());
734 //			SimpleGradientPanel progressPanel = new SimpleGradientPanel();
735 //			JLabel wordsLabel = new JLabel("Project Complete: ");
736 //			wordsLabel.setOpaque(false);
737 //			progressPanel.add(wordsLabel);
738 //			
739 //	        percentageCompleteBar.setStringPainted(true);
740 //	        percentageCompleteBar.setBorderPainted(true); 
741 //	        percentageCompleteBar.setOpaque(false);
742 //	        
743 //	        progressPanel.add(percentageCompleteBar);
744 //	        
745 //	        JLabel currentScoreLabel = new JLabel("Current Score:");
746 //	        
747 //	        JPanel rawPanel = new JPanel(new FlowLayout());
748 //	        
749 //	        currentScoreLabel.setOpaque(false);
750 //	        currentScoreEquationLabel.setOpaque(false);
751 //	        
752 //	        rawPanel.add(currentScoreLabel);
753 //	        rawPanel.add(currentScoreEquationLabel);
754 //	        rawPanel.setOpaque(false);
755 //	        
756 //	        progressPanel.add(rawPanel);
757 //	        
758 //			outerPanel.add(titleAndButtonPanel,BorderLayout.NORTH);
759 //			outerPanel.add(progressPanel, BorderLayout.CENTER);
760 //			
761 //			mainShowAllWorkPanel.add(outerPanel,BorderLayout.NORTH);
762 //			mainShowAllWorkPanel.add(spane,BorderLayout.CENTER);
763 //			return mainShowAllWorkPanel;
764 //		}
765 		
766 		
767 		mainShowAllWorkPanel.add(titleAndButtonPanel,BorderLayout.NORTH);
768 		mainShowAllWorkPanel.add(spane,BorderLayout.CENTER);
769 		return mainShowAllWorkPanel;
770 	}
771 
772 /******************************************************************************************/	
773 /******************************************************************************************/	
774 	
775 	/***
776 	 * sets and returns the activity title label
777 	 * 
778 	 * @param i
779 	 * @param activity
780 	 * @return actTitle
781 	 */
782 	private JLabel getActivityTitle(int i, PasActivity activity) {
783 		float headerFontSize = 16.0f;
784 		String actTitle = "";
785 		if(activity.getTitle().indexOf("Activity") > -1){
786 			actTitle = activity.getTitle(); 
787 		}else{
788 			actTitle = "Activity " + (i+1) + ": " + activity.getTitle();
789 		}
790 		
791 		JLabel actTitleLabel = new JLabel(actTitle);
792 		actTitleLabel.setFont(actTitleLabel.getFont().deriveFont(Font.BOLD, headerFontSize));
793 		actTitleLabel.setBorder(BorderFactory.createEmptyBorder(2, 2, 2, 2));
794 		actTitleLabel.setBackground(actTitleLabel.getBackground().brighter());
795 		return actTitleLabel;
796 	}
797 
798 	
799 	/***
800 	 * creates step title button 
801 	 * 
802 	 * @param thisPanel
803 	 * @param j
804 	 * @param step
805 	 * @return title
806 	 */
807 	private JButton createStepTitleButton(PasProjectNavigationTaskPanel thisPanel, int j,
808 			PasStep step) {
809 		JButton title = new JButton(new NavigateAction(step, navigationService,thisPanel));
810 		title.setHorizontalTextPosition(JLabel.LEFT);
811 		title.setContentAreaFilled(false);
812 		title.setFont(title.getFont().deriveFont(16.0f));
813 		title.setBorder(BorderFactory.createEmptyBorder(0, 0, 8, 0));					
814 		title.setText("Step " + (j + 1) + " : " + title.getText());
815 		return title;
816 	}
817 	
818 	
819 	/***
820 	 * processes and returns teacher comments (annotations) 
821 	 * 
822 	 * @return comments
823 	 */
824 	public static String processTheAnnotations(PasStep step, int rdIndex, PasProject project){
825 		
826 		String comments = null;
827 		if (step instanceof Assessment) {
828 			Assessment assmtStep = ((Assessment)step);
829 			
830 			List<ResponseDeclaration> responseDeclarations = assmtStep.getAssessmentItem()
831 			.getResponseDeclarations();
832 
833 			ResponseDeclaration rd = null;
834 			if(responseDeclarations !=null) {
835 				rd = responseDeclarations.get(rdIndex);
836 			} else {
837 				rd = null;
838 			}
839 			comments = AnnotationUtils.processTheAnnotations(step, assmtStep.getSessionService(), assmtStep.getAgentService(), project.getAnnotationService());		
840 			
841 //			IAnnotation annotation;
842 //			Pod pod = (Pod) step.getBeanContext();
843 //
844 //			User user = project.getSessionService().getUsers().iterator().next();
845 //			AgentSet agentsOfUser = ((Assessment) step).agentService.getAgentsOfUser(user);
846 //			AgentSet agentsOfUserInWorkgroup = 
847 //				agentsOfUser.select(Role.RUN_WORKGROUP);
848 //			IAgent agent=null;
849 //			try {
850 //				agent = agentsOfUserInWorkgroup.getSingle();
851 //			} catch (MismatchedAgentSetSizeException e1) {
852 //				e1.printStackTrace();
853 //				//return null;
854 //			}
855 //			annotation = project.getAnnotationService().getAnnotation(pod, agent, "http://telscenter.org/annotation/comments");			
856 //			if (annotation != null) {
857 //				comments = annotation.getContents();
858 			}	
859 
860 			
861 //			if (!(step instanceof Note)) {   // for a note, we have one comment for all parts, not one comment per part
862 //				AssessmentItem assessmentItem = ((Assessment)step).assessmentItem;
863 //				List<ResponseDeclaration> responseDeclarations = assessmentItem
864 //				.getResponseDeclarations();
865 //
866 //				if(responseDeclarations !=null) {
867 //					ResponseDeclaration rd = responseDeclarations.get(rdIndex);
868 //					if (rd != null) {
869 //						Rim rim = rd.getRim();
870 //
871 //						if(rim!=null){
872 //							try {
873 //								IAnnotation rimAnnotation = project.getAnnotationService().getAnnotation(rim, agent, "http://telscenter.org/annotation/comments");
874 //								if (rimAnnotation != null) {
875 ////									System.out.println("Rim: " + rim.toString());
876 ////									System.out.println("RimAnnotation: " + rimAnnotation);
877 //									annotation = rimAnnotation;
878 //									comments = annotation.getContents();
879 ////									System.out.println("annotation ");
880 ////									System.out.println("  source: " + annotation.getSource());
881 ////									System.out.println("  contentType: " + annotation.getContentType());
882 ////									System.out.println("  contents: " + annotation.getContents());
883 //								}
884 //							} catch(Exception e){
885 //								e.printStackTrace();
886 //							}
887 //						}
888 //					}
889 //				}
890 //				
891 //			}
892 //		}
893 		
894 		return comments;
895 		
896 	}
897 	
898 	/***
899 	 * processes and returns teacher score (annotations) 
900 	 * 
901 	 * @return comments
902 	 */
903 	public static String processScore(PasStep step, int rdIndex, PasProject project){
904 			
905 			
906 			String score = null;
907 			if (step instanceof Assessment) {
908 				Assessment assmtStep = ((Assessment)step);
909 				
910 				List<ResponseDeclaration> responseDeclarations = assmtStep.getAssessmentItem()
911 				.getResponseDeclarations();
912 
913 				ResponseDeclaration rd = null;
914 				if(responseDeclarations !=null) {
915 					rd = responseDeclarations.get(rdIndex);
916 				} else {
917 					rd = null;
918 				}
919 				score = AnnotationUtils.processScore(step, assmtStep.getSessionService(), assmtStep.getAgentService(), project.getAnnotationService());		
920 				
921 			}
922 //			IAnnotation scoreAnnotation;
923 //			Pod pod = (Pod) step.getBeanContext();
924 //
925 //			User user = project.getSessionService().getUsers().iterator().next();
926 //			AgentSet agentsOfUser = ((Assessment) step).agentService.getAgentsOfUser(user);
927 //			AgentSet agentsOfUserInWorkgroup = 
928 //				agentsOfUser.select(Role.RUN_WORKGROUP);
929 //			IAgent agent=null;
930 //			try {
931 //				agent = agentsOfUserInWorkgroup.getSingle();
932 //			} catch (MismatchedAgentSetSizeException e1) {
933 //				e1.printStackTrace();
934 //				//return null;
935 //			}
936 //
937 //			scoreAnnotation = project.getAnnotationService().getAnnotation(pod, agent, "http://telscenter.org/annotation/score");
938 //			if (scoreAnnotation != null) {
939 //				score = scoreAnnotation.getContents();
940 //			}	
941 
942 //			
943 //			if (!(step instanceof Note)) {   // for a note, we have one comment for all parts, not one comment per part
944 //				AssessmentItem assessmentItem = ((Assessment)step).assessmentItem;
945 //				List<ResponseDeclaration> responseDeclarations = assessmentItem
946 //				.getResponseDeclarations();
947 //
948 //				if(responseDeclarations !=null) {
949 //					ResponseDeclaration rd = responseDeclarations.get(rdIndex);
950 //					if (rd != null) {
951 //						Rim rim = rd.getRim();
952 //
953 //						if(rim!=null){
954 //							try {
955 //								IAnnotation rimAnnotation = project.getAnnotationService().getAnnotation(rim, agent, "http://telscenter.org/annotation/comments");
956 //								if (rimAnnotation != null) {
957 ////									System.out.println("Rim: " + rim.toString());
958 ////									System.out.println("RimAnnotation: " + rimAnnotation);
959 //									scoreAnnotation = rimAnnotation;
960 //									score = scoreAnnotation.getContents();
961 ////									System.out.println("annotation ");
962 ////									System.out.println("  source: " + scoreAnnotation.getSource());
963 ////									System.out.println("  contentType: " + scoreAnnotation.getContentType());
964 ////									System.out.println("  contents: " + scoreAnnotation.getContents());
965 //								}
966 //							} catch(Exception e){
967 //								e.printStackTrace();
968 //							}
969 //						}
970 //					}
971 //				}
972 //				
973 //			}
974 //		}
975 		
976 		return score;
977 		
978 	}
979 	
980 	
981 	/***
982 	 * proceeds to retrieve the current student part and set its size before returning it
983 	 * 
984 	 * @param theParts
985 	 * @param i
986 	 * @return studentPart
987 	 */
988 	private JPanel getStudentPart(List<JPanel> theParts, int i) {
989 		JPanel studentPart = theParts.get(i); 
990 		studentPart.setAlignmentY(Component.TOP_ALIGNMENT);
991 		//studentPart.setBackground(Color.RED);
992 		return studentPart;
993 	}
994 
995 	/***
996 	 * proceeds to set the teacher comments panel with an appropriate size before returning it
997 	 * 
998 	 * @param comments
999 	 * @return commentPanel
1000 	 */
1001 	private JPanel makeTeacherCommentPanel(String comments) {
1002 		JPanel commentPanel = new JPanel(new BorderLayout(0,0));
1003 		
1004 		JTextArea textArea;
1005 		if( comments == null || StringUtils.trimToNull(comments) == null) {
1006 			textArea = new JTextArea(0,0);
1007 			//textArea.setPreferredSize(new Dimension(290,50));
1008 			comments = "  Uncommented\n\n";
1009 			textArea.setSize(290, textArea.getPreferredSize().height);
1010 			textArea.setForeground(Color.RED);
1011 		} else {
1012 			textArea = new JTextArea(0,0);
1013 			textArea.setSize(290, textArea.getPreferredSize().height);
1014 			textArea.setBackground(new Color(255,255,204));
1015 		}// if
1016 		
1017 		
1018 		textArea.setLineWrap(true);
1019 		textArea.setWrapStyleWord(true);
1020 		textArea.setEditable(false);
1021 		
1022 		textArea.setText(comments);
1023 		textArea.setBorder(BorderFactory.createEmptyBorder());
1024 		JScrollPane scrollPane = new JScrollPane(textArea);
1025 		scrollPane.setBorder(BorderFactory.createLineBorder(Color.black, 1));
1026 		commentPanel.add(scrollPane,BorderLayout.CENTER);
1027 		commentPanel.setBackground(Color.WHITE);
1028 		commentPanel.setBorder(createEmptyTitledBorder("Teacher Comments",commentPanel));
1029 		return commentPanel;
1030 	}
1031 
1032 
1033 	private String wrapText(String comments, double textWidth){		
1034 		String initHtml = "<html><body>";
1035 		String finalHtml = "</body></html>";
1036 		String finalStr = "";	
1037 		int lastIndex = 0;
1038 
1039 		comments.trim();
1040 
1041 		while(comments.length() > textWidth){
1042 			String substri = comments.substring(0,(int)textWidth);
1043 			lastIndex = substri.lastIndexOf(" ");
1044 			finalStr = finalStr + substri.substring(0,lastIndex) + "\n";
1045 			comments = comments.substring((int)lastIndex, comments.length());
1046 
1047 		}
1048 		
1049 		return initHtml + finalStr + comments.substring(0,comments.length()) + finalHtml;		
1050 	}
1051 
1052 
1053 	public void setServiceProvider(PasProjectServiceProvider provider){
1054 		this.provider = provider;
1055 	}
1056 	
1057 	private void setStepTitlePanelVisited(boolean isVisited){
1058 		this.visited = isVisited;
1059 	}
1060 	
1061 	public boolean getStepTitlePanelVisited(){
1062 		return this.visited;
1063 	}
1064 	
1065 	/***
1066 	 * gets the component by name
1067 	 * 
1068 	 * @param container
1069 	 * @param name
1070 	 * @return
1071 	 */
1072 	public static Component getByName(Container container,String name) {
1073 		  for (int i = 0; i < container.getComponentCount(); i++) {
1074 		    if (name.equals(container.getComponent(i).getName())) {
1075 		      return container.getComponent(i);
1076 		    }
1077 		  }
1078 		  return null;
1079 	}
1080 
1081 }