package edu.vserver.exercises.math.essentials.layout; import org.vaadin.jouni.animator.AnimatorProxy; import org.vaadin.jouni.animator.AnimatorProxy.AnimationListener; import org.vaadin.jouni.animator.shared.AnimType; import com.vaadin.shared.ui.label.ContentMode; import com.vaadin.ui.Alignment; import com.vaadin.ui.Button; import com.vaadin.ui.Button.ClickListener; import com.vaadin.ui.CssLayout; import com.vaadin.ui.HorizontalLayout; import com.vaadin.ui.Label; import com.vaadin.ui.UI; import com.vaadin.ui.VerticalLayout; import com.vaadin.ui.Window; import fi.utu.ville.exercises.helpers.StandardSubmissionType; import fi.utu.ville.exercises.layout.AssignmentProgressBar; import fi.utu.ville.exercises.layout.PhasedAssignmentNavigation; import fi.utu.ville.exercises.model.ExecutionSettings; import fi.utu.ville.standardutils.Localizer; import fi.utu.ville.standardutils.StandardIcon.Icon; import fi.utu.ville.standardutils.StandardUIFactory; import fi.utu.ville.standardutils.UIConstants; public class MathLayout<P extends Problem> extends CssLayout implements MathLayoutController { private static final long serialVersionUID = 2062189376088801532L; private ExecutionSettings execSettings; private AbstractMathExecutor<?, ?, P> exerExecutor; public org.vaadin.jouni.animator.AnimatorProxy.Animation aPrev, aNext, aCheck; private CssLayout exWrapper; private CssLayout animationWrap; private final MathAssignmentProgressBar progress; private final PhasedAssignmentNavigation navigation; private final AnimatorProxy proxy; public static final int shiftSize = 2000; private final TimeStampHandler timeStampHandler; public MathLayout(final Localizer localizer, final MathExerciseView<P> exView, final MathExerciseState<P> exState, TimeStampHandler timeStampHandler, final ExecutionSettings execSettings) { this.execSettings = execSettings; exView.setLayoutController(this); navigation = new PhasedAssignmentNavigation(localizer); exWrapper = new CssLayout(); exWrapper.setStyleName("math-layout-exer-wrapper"); initAnimationWrap(exView); this.timeStampHandler = timeStampHandler; proxy = new AnimatorProxy(); proxy.addListener(new AnimationListener() { @Override public void onAnimation(org.vaadin.jouni.animator.AnimatorProxy.AnimationEvent event) { if (event.getAnimation() == aNext) { exView.clearFields(); navigation.setPrevButtonEnabled(false); navigation.setNextButtonEnabled(false); progress.setCurrentStepCorrect(exState.getCurrentProblem().isCorrect()); progress.nextStep(); initAnimationWrap(exView); proxy.animate(animationWrap, AnimType.FADE_IN) .setDuration(500) .setDelay(20); navigation.setCheckButtonEnabled(true); navigation.focusCheck(); exView.drawProblem(exState.nextProblem()); exerExecutor.startMathPerformance(exState.getCurrentProblem()); } else if (event.getAnimation() == aPrev) { exView.clearFields(); navigation.setPrevButtonEnabled(false); navigation.setNextButtonEnabled(false); progress.previousStep(); initAnimationWrap(exView); proxy.animate(animationWrap, AnimType.FADE_IN) .setDuration(500) .setDelay(20); } else if (event.getAnimation() == aCheck) { exState.tryAnswer(exView.getAnswer(), execSettings.isExam()); exerExecutor.setUnsubmittedChangesFlag(true); if (!execSettings.isNoCorrAnswers()) { exView.showSolution(exState.getCurrentProblem()); } exerExecutor.finishMathPerformance(exState.getCurrentProblem()); MathLayout.this.timeStampHandler .add("Question" + TimeStampHandler.separator + exState.getCurrentProblem().getQuestion( localizer) + TimeStampHandler.separator + "UserAnswer" + TimeStampHandler.separator + exState.getCurrentProblem().getUserAnswer() + TimeStampHandler.separator + "CorrectAnswer" + TimeStampHandler.separator + exState.getCurrentProblem().getCorrectAnswer() + TimeStampHandler.separator + "isCorrect" + TimeStampHandler.separator + exState.getCurrentProblem().isCorrect()); navigation.setCheckButtonEnabled(false); if (exState.hasNextProblem()) { navigation.setNextButtonEnabled(true); navigation.focusNext(); } else { exView.lockControls(); progress.nextStep(exState.getCurrentProblem().isCorrect()); final Window confirm = new Window(localizer .getUIText(UIConstants.SUBMIT_QUESTION)); confirm.setModal(true); confirm.setWidth("600px"); confirm.setHeight("330px"); confirm.setCaption(""); confirm.setStyleName("opaque"); confirm.addStyleName("unclosable-window"); confirm.setClosable(false); confirm.addStyleName("submit-window"); VerticalLayout content = new VerticalLayout(); content.setSizeFull(); content.setMargin(true); Label question = new Label(localizer .getUIText(UIConstants.SUBMIT_QUESTION)); question.setContentMode(ContentMode.HTML); question.addStyleName("big-text-white"); question.setSizeUndefined(); content.addComponent(question); content.setComponentAlignment(question, Alignment.TOP_CENTER); confirm.setContent(content); // Button holder (back to round, replay, next) HorizontalLayout buttons = new HorizontalLayout(); buttons.addStyleName("submit-buttons-container"); buttons.setWidth("100%"); buttons.setSpacing(true); content.addComponent(buttons); content.setComponentAlignment(buttons, Alignment.TOP_CENTER); Button submit = StandardUIFactory .getRoundButton(Icon.SUBMIT); submit.setDescription( localizer.getUIText(UIConstants.SUBMIT)); Button cancel = StandardUIFactory .getRoundButton(Icon.CLOSE); cancel.setDescription( localizer.getUIText(UIConstants.CLOSE)); buttons.addComponents(submit, cancel); buttons.setComponentAlignment(submit, Alignment.MIDDLE_CENTER); buttons.setComponentAlignment(cancel, Alignment.MIDDLE_CENTER); submit.addClickListener(e -> { exerExecutor.askSubmit(StandardSubmissionType.NORMAL); confirm.close(); }); cancel.addClickListener(e -> confirm.close()); UI.getCurrent().addWindow(confirm); } proxy.animate(animationWrap, AnimType.FADE_IN).setDuration(250) .setDelay(50); } } }); // Constructors. progress = new MathAssignmentProgressBar(exState.getProblemCount(), !execSettings.isNoCorrAnswers()); navigation.setNextButtonEnabled(false); navigation.focusCheck(); addComponents(progress, navigation, exWrapper, proxy); setStyleName("math-layout"); setSizeFull(); } private void initAnimationWrap(MathExerciseView<P> exView) { animationWrap = new CssLayout(); animationWrap.setSizeFull(); animationWrap.addComponent(exView); exWrapper.removeAllComponents(); exWrapper.addComponent(animationWrap); } public CssLayout getAnimationWrapper() { return animationWrap; } public AssignmentProgressBar getProgressBar() { return progress; } public void attachExecutor(AbstractMathExecutor<?, ?, P> exerExecutor) { this.exerExecutor = exerExecutor; } public void attachControllers(ClickListener prevController, ClickListener checkController, ClickListener nextController) { navigation.addPrevButtonListener(prevController); navigation.addCheckButtonListener(checkController); navigation.addNextButtonListener(nextController); } public void attachExecSettings(ExecutionSettings execSettings) { this.execSettings = execSettings; } public AnimatorProxy getProxy() { return proxy; } @Override public Button getCheckBtn() { return navigation.getCheckButton(); } public void reset() { navigation.setPrevButtonEnabled(false); navigation.setCheckButtonEnabled(true); navigation.setNextButtonEnabled(false); progress.reset(); } @Override public void setCheckButtonEnabled(boolean enabled) { navigation.setCheckButtonEnabled(enabled); } }