/**
* OLAT - Online Learning and Training<br>
* http://www.olat.org
* <p>
* Licensed under the Apache License, Version 2.0 (the "License"); <br>
* you may not use this file except in compliance with the License.<br>
* You may obtain a copy of the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing,<br>
* software distributed under the License is distributed on an "AS IS" BASIS, <br>
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br>
* See the License for the specific language governing permissions and <br>
* limitations under the License.
* <p>
* Copyright (c) since 2004 at Multimedia- & E-Learning Services (MELS),<br>
* University of Zurich, Switzerland.
* <hr>
* <a href="http://www.openolat.org">
* OpenOLAT - Online Learning and Training</a><br>
* This file has been modified by the OpenOLAT community. Changes are licensed
* under the Apache 2.0 license as the original file.
*/
package org.olat.ims.qti.editor;
import org.olat.core.gui.UserRequest;
import org.olat.core.gui.components.form.flexible.FormItem;
import org.olat.core.gui.components.form.flexible.FormItemContainer;
import org.olat.core.gui.components.form.flexible.elements.IntegerElement;
import org.olat.core.gui.components.form.flexible.elements.RichTextElement;
import org.olat.core.gui.components.form.flexible.elements.SingleSelection;
import org.olat.core.gui.components.form.flexible.elements.TextElement;
import org.olat.core.gui.components.form.flexible.impl.FormBasicController;
import org.olat.core.gui.components.form.flexible.impl.FormEvent;
import org.olat.core.gui.components.form.flexible.impl.FormLayoutContainer;
import org.olat.core.gui.components.form.flexible.impl.elements.richText.RichTextConfiguration;
import org.olat.core.gui.components.tabbedpane.TabbedPane;
import org.olat.core.gui.control.Controller;
import org.olat.core.gui.control.ControllerEventListener;
import org.olat.core.gui.control.WindowControl;
import org.olat.core.gui.control.generic.tabbable.TabbableController;
import org.olat.ims.qti.editor.beecom.objects.Duration;
import org.olat.ims.qti.editor.beecom.objects.Section;
import org.olat.ims.qti.editor.beecom.objects.SelectionOrdering;
/**
*
* Initial date: 05.03.2014<br>
* @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
*
*/
public class SectionController extends FormBasicController implements TabbableController, ControllerEventListener {
private static final String[] yesnoKeys = new String[] { "y", "n" };
private TextElement titleEl;
private IntegerElement timeMinEl, timeSecEl;
private RichTextElement objectivesEl;
private SingleSelection limitTimeEl, shuffleEl, selectionNumEl;
private Section section;
private final QTIEditorPackage qtiPackage;
private final boolean restrictedEdit;
/**
* @param section
* @param qtiPackage
* @param locale
* @param wControl
*/
public SectionController(Section section, QTIEditorPackage qtiPackage, UserRequest ureq, WindowControl wControl, boolean restrictedEdit) {
super(ureq, wControl);
this.restrictedEdit = restrictedEdit;
this.section = section;
this.qtiPackage = qtiPackage;
/*
main.contextPut("mediaBaseURL", qtiPackage.getMediaBaseURL());
*/
initForm(ureq);
}
@Override
protected void initForm(FormItemContainer formLayout, Controller listener, UserRequest ureq) {
setFormTitle("fieldset.legend.sectionsettings");
setFormContextHelp("Test and Questionnaire Editor in Detail#details_testeditor_test_konf");
String title = section.getTitle();
titleEl = uifactory.addTextElement("title", "form.metadata.title", 255, title, formLayout);
String objectives = section.getObjectives();
objectivesEl = uifactory.addRichTextElementForStringData("objectives", "form.metadata.objectives", objectives, 6, 12, false,
qtiPackage.getBaseDir(), null, formLayout, ureq.getUserSession(), getWindowControl());
RichTextConfiguration richTextConfig = objectivesEl.getEditorConfiguration();
// disable <p> element for enabling vertical layouts
richTextConfig.disableRootParagraphElement();
// set upload dir to the media dir
richTextConfig.setFileBrowserUploadRelPath("media");
// manually enable the source edit button
richTextConfig.enableCode();
//allow script tags...
richTextConfig.setInvalidElements(RichTextConfiguration.INVALID_ELEMENTS_FORM_FULL_VALUE_UNSAVE_WITH_SCRIPT);
richTextConfig.setExtendedValidElements("script[src,type,defer]");
//form.section.durationswitch
String[] yesnoValues = new String[] { translate("yes"), translate("no") };
limitTimeEl = uifactory.addRadiosHorizontal("form.section.durationswitch", formLayout, yesnoKeys, yesnoValues);
limitTimeEl.addActionListener(FormEvent.ONCHANGE);
limitTimeEl.setEnabled(!restrictedEdit);
timeMinEl = uifactory.addIntegerElement("form.imd.time.min", 0, formLayout);
timeMinEl.setDisplaySize(3);
timeMinEl.setEnabled(!restrictedEdit);
timeSecEl = uifactory.addIntegerElement("form.imd.time.sek", 0, formLayout);
timeSecEl.setDisplaySize(3);
timeSecEl.setEnabled(!restrictedEdit);
if (section.getDuration() != null && section.getDuration().isSet()) {
limitTimeEl.select(yesnoKeys[0], true);
timeMinEl.setIntValue(section.getDuration().getMin());
timeSecEl.setIntValue(section.getDuration().getSec());
} else {
limitTimeEl.select(yesnoKeys[1], true);
timeMinEl.setVisible(false);
timeSecEl.setVisible(false);
}
//ordering
boolean random = SelectionOrdering.RANDOM.equals(section.getSelection_ordering().getOrderType());
shuffleEl = uifactory.addRadiosHorizontal("shuffle", "form.section.shuffle", formLayout, yesnoKeys, yesnoValues);
shuffleEl.addActionListener(FormEvent.ONCHANGE);
shuffleEl.setEnabled(!restrictedEdit);
if (random) {
shuffleEl.select(yesnoKeys[0], true);
} else {
shuffleEl.select(yesnoKeys[1], true);
}
int numOfItems = section.getItems().size();
String[] theKeys = new String[numOfItems + 1];
String[] theValues = new String[numOfItems + 1];
theKeys[0] = "0";
theValues[0] = translate("form.section.selection_all");
for(int i=0; i<numOfItems; i++) {
theKeys[i+1] = Integer.toString(i+1);
theValues[i+1] = Integer.toString(i+1);
}
selectionNumEl = uifactory.addDropdownSingleselect("selection.num", "form.section.selection_pre", formLayout, theKeys, theValues, null);
selectionNumEl.setHelpText(translate("form.section.selection_pre.hover"));
selectionNumEl.setEnabled(!restrictedEdit);
int selectionNum = section.getSelection_ordering().getSelectionNumber();
if(selectionNum <= 0) {
selectionNumEl.select(theKeys[0], true);
} else if(selectionNum > 0 && selectionNum < theKeys.length) {
selectionNumEl.select(theKeys[selectionNum], true);
} else {
selectionNumEl.select(theKeys[theKeys.length - 1], true);
}
FormLayoutContainer buttonsCont = FormLayoutContainer.createButtonLayout("buttons", getTranslator());
formLayout.add(buttonsCont);
uifactory.addFormSubmitButton("submit", buttonsCont);
}
public void childNodeChanges() {
int numOfItems = section.getItems().size();
String[] theKeys = new String[numOfItems + 1];
String[] theValues = new String[numOfItems + 1];
theKeys[0] = "0";
theValues[0] = translate("form.section.selection_all");
for(int i=0; i<numOfItems; i++) {
theKeys[i+1] = Integer.toString(i+1);
theValues[i+1] = Integer.toString(i+1);
}
String selectedKey = selectionNumEl.isOneSelected() ? selectionNumEl.getSelectedKey() : null;
selectionNumEl.setKeysAndValues(theKeys, theValues, null);
//reselect the key
if(selectedKey != null && shuffleEl.isOneSelected() && shuffleEl.isSelected(0)) {
boolean found = false;
for(String theKey:theKeys) {
if(selectedKey.equals(theKey)) {
found = true;
}
}
if(found) {
selectionNumEl.select(selectedKey, true);
} else {
selectionNumEl.select(theKeys[theKeys.length - 1], true);
}
}
}
protected void doDispose() {
//
}
@Override
protected void formOK(UserRequest ureq) {
String newTitle = titleEl.getValue();
if (newTitle.trim().isEmpty()) { // Remove empty title to fix OLAT-2296
newTitle = "";
}
String oldTitle = section.getTitle();
boolean hasTitleChange = newTitle != null && !newTitle.equals(oldTitle);
String newObjectives = objectivesEl.getValue();
String oldObjectives = section.getObjectives();
boolean hasObjectivesChange = newObjectives != null && !newObjectives.equals(oldObjectives);
NodeBeforeChangeEvent nce = new NodeBeforeChangeEvent();
if (hasTitleChange) {
nce.setNewTitle(newTitle);
}
if (hasObjectivesChange) {
nce.setNewObjectives(newObjectives);
}
if (hasTitleChange || hasObjectivesChange) {
// create a memento first
nce.setSectionIdent(section.getIdent());
fireEvent(ureq, nce);
// then apply changes
section.setTitle(newTitle);
section.setObjectives(newObjectives);
}
if (!restrictedEdit) {
String selectionNumStr = selectionNumEl.getSelectedKey();
int selectionNum = 1;
try {
selectionNum = Integer.parseInt(selectionNumStr);
} catch(NumberFormatException e) {
logWarn("", e);
}
section.getSelection_ordering().setSelectionNumber(selectionNum);
boolean randomType = shuffleEl.isOneSelected() && shuffleEl.isSelected(0);
if(randomType) {
section.getSelection_ordering().setOrderType(SelectionOrdering.RANDOM);
} else {
section.getSelection_ordering().setOrderType(SelectionOrdering.SEQUENTIAL);
}
boolean duration = limitTimeEl.isOneSelected() && limitTimeEl.isSelected(0);
if (duration) {
String durationMin = timeMinEl.getValue();
String durationSec = timeSecEl.getValue();
try {
Integer.parseInt(durationMin);
int sec = Integer.parseInt(durationSec);
if (sec > 60) throw new NumberFormatException();
} catch (NumberFormatException nfe) {
durationMin = "0";
durationSec = "0";
showWarning("error.duration");
}
Duration d = new Duration(durationMin, durationSec);
section.setDuration(d);
timeMinEl.setIntValue(d.getMin());
timeSecEl.setIntValue(d.getSec());
} else {
section.setDuration(null);
}
}
qtiPackage.serializeQTIDocument();
}
@Override
protected void formInnerEvent(UserRequest ureq, FormItem source, FormEvent event) {
if (limitTimeEl == source) {
boolean enabled = limitTimeEl.isOneSelected() && limitTimeEl.isSelected(0);
timeMinEl.setVisible(enabled);
timeSecEl.setVisible(enabled);
}
super.formInnerEvent(ureq, source, event);
}
public void addTabs(TabbedPane tabbedPane) {
tabbedPane.addTab(translate("tab.section"), getInitialComponent());
}
}