/**
* <a href="http://www.openolat.org">
* OpenOLAT - Online Learning and Training</a><br>
* <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 the
* <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache homepage</a>
* <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>
* Initial code contributed and copyrighted by<br>
* BPS Bildungsportal Sachsen GmbH, http://www.bps-system.de
* <p>
*/
package de.bps.course.nodes.ll;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import org.olat.core.commons.controllers.linkchooser.MediaChooserController;
import org.olat.core.commons.controllers.linkchooser.URLChoosenEvent;
import org.olat.core.gui.UserRequest;
import org.olat.core.gui.components.Component;
import org.olat.core.gui.components.form.ValidationError;
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.FormLink;
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.elements.FormLinkImpl;
import org.olat.core.gui.components.form.flexible.impl.elements.FormSubmit;
import org.olat.core.gui.components.form.flexible.impl.elements.ItemValidatorProvider;
import org.olat.core.gui.components.link.Link;
import org.olat.core.gui.control.Controller;
import org.olat.core.gui.control.Event;
import org.olat.core.gui.control.WindowControl;
import org.olat.core.gui.control.generic.closablewrapper.CloseableModalController;
import org.olat.core.helpers.Settings;
import org.olat.core.util.StringHelper;
import org.olat.core.util.vfs.VFSContainer;
import org.olat.course.editor.NodeEditController;
import org.olat.course.run.environment.CourseEnvironment;
import org.olat.modules.ModuleConfiguration;
import de.bps.course.nodes.LLCourseNode;
/**
* Description:<br>
* Edit form for link lists.
*
* <P>
* Initial Date: 17.11.2008 <br>
*
* @author Marcel Karras (toka@freebits.de)
*/
public class LLEditForm extends FormBasicController {
private static final String BLANK_KEY = "_blank";
private static final String SELF_KEY = "_self";
private ModuleConfiguration moduleConfig;
private FormSubmit subm;
private List<TextElement> lTargetInputList;
private List<SingleSelection> lHtmlTargetInputList;
private List<TextElement> lDescriptionInputList;
private List<TextElement> lCommentInputList;
private List<FormLink> lDelButtonList;
private List<FormLink> lCustomMediaButtonList;
private List<LLModel> linkList;
private List<FormLink> lAddButtonList;
private long counter = 0;
private MediaChooserController mediaChooserController;
private CloseableModalController mediaDialogBox;
private LLModel currentLink;
private final CourseEnvironment courseEnv;
public LLEditForm(UserRequest ureq, WindowControl wControl, ModuleConfiguration moduleConfig, CourseEnvironment courseEnv) {
super(ureq, wControl, "editForm");
this.moduleConfig = moduleConfig;
// read existing links from config
linkList = new ArrayList<LLModel>(moduleConfig.getList(LLCourseNode.CONF_LINKLIST, LLModel.class));
// list of all link target text fields
lTargetInputList = new ArrayList<TextElement>(linkList.size());
// list of all link html target text fields
lHtmlTargetInputList = new ArrayList<SingleSelection>(linkList.size());
// list of all link description text fields
lDescriptionInputList = new ArrayList<TextElement>(linkList.size());
// list of all link comment text fields
lCommentInputList = new ArrayList<TextElement>(linkList.size());
// list of all link add action buttons
lAddButtonList = new ArrayList<FormLink>(linkList.size());
// list of all link deletion action buttons
lDelButtonList = new ArrayList<FormLink>(linkList.size());
//list of all custom media buttons
lCustomMediaButtonList = new ArrayList<FormLink>(linkList.size());
this.courseEnv = courseEnv;
initForm(ureq);
}
/**
* {@inheritDoc}
*/
@Override
protected void doDispose() {
// nothing to dispose
}
/**
* {@inheritDoc}
*/
@Override
protected void formOK(UserRequest ureq) {
// read data from form elements
for (int i = 0; i < lTargetInputList.size(); i++) {
LLModel link = (LLModel) lTargetInputList.get(i).getUserObject();
String linkValue = lTargetInputList.get(i).getValue();
if(link.isIntern()) {
if(!linkValue.contains("://") && !linkValue.startsWith("/")) {
linkValue = "/".concat(linkValue.trim());
lTargetInputList.get(i).setValue(linkValue);
}
} else if(!linkValue.contains("://")) {
linkValue = "http://".concat(linkValue.trim());
lTargetInputList.get(i).setValue(linkValue);
}
link.setTarget(linkValue);
boolean blank = lHtmlTargetInputList.get(i).isSelected(0);
if(linkValue.startsWith(Settings.getServerContextPathURI())) {
// links to OO pages open in same window
blank = false;
lHtmlTargetInputList.get(i).select(SELF_KEY, true);
}
link.setHtmlTarget(blank ? BLANK_KEY : SELF_KEY);
link.setDescription(lDescriptionInputList.get(i).getValue());
link.setComment(lCommentInputList.get(i).getValue());
}
moduleConfig.set(LLCourseNode.CONF_LINKLIST, linkList);
// Inform all listeners about the changes
fireEvent(ureq, NodeEditController.NODECONFIG_CHANGED_EVENT);
}
/**
* {@inheritDoc}
*/
@Override
protected void formInnerEvent(UserRequest ureq, FormItem source, FormEvent event) {
if (source instanceof TextElement) {
int i = lTargetInputList.indexOf(source);
if (i >= 0) {
String linkValue = ((TextElement)source).getValue();
if(!linkValue.contains("://")) {
linkValue = "http://".concat(linkValue.trim());
}
boolean selected = lHtmlTargetInputList.get(i).isSelected(0);
if(selected && linkValue.startsWith(Settings.getServerContextPathURI())) {
lHtmlTargetInputList.get(i).select(BLANK_KEY, false);
}
}
}
else if (source.getComponent() instanceof Link) {
if (lAddButtonList.contains(source)) {
// add a new form link
final LLModel link = (LLModel) ((FormLink) source).getUserObject();
final LLModel newLink = new LLModel();
linkList.add(linkList.indexOf(link) + 1, newLink);
addNewFormLink(linkList.indexOf(link) + 1, newLink);
} else if (lDelButtonList.contains(source)) {
// special case: only one line existent
if (linkList.size() == 1) {
// clear this line
lTargetInputList.get(0).setValue("");
lTargetInputList.get(0).setEnabled(true);
lDescriptionInputList.get(0).setValue("");
lCommentInputList.get(0).setValue("");
} else {
final LLModel link = (LLModel) ((FormLink) source).getUserObject();
removeFormLink(link);
}
} else if (lCustomMediaButtonList.contains(source)) {
currentLink = (LLModel) ((FormLink) source).getUserObject();
removeAsListenerAndDispose(mediaDialogBox);
removeAsListenerAndDispose(mediaChooserController);
VFSContainer courseContainer = courseEnv.getCourseFolderContainer();
mediaChooserController = new MediaChooserController(ureq, getWindowControl(), courseContainer, null, null, "", null, true);
listenTo(mediaChooserController);
mediaDialogBox = new CloseableModalController(getWindowControl(), translate("choose"), mediaChooserController.getInitialComponent());
mediaDialogBox.activate();
listenTo(mediaDialogBox);
}
}
super.formInnerEvent(ureq, source, event);
fireEvent(ureq, NodeEditController.NODECONFIG_CHANGED_EVENT);
}
@Override
public void event(UserRequest ureq, Component source, Event event) {
super.event(ureq, source, event);
}
@Override
protected void event(UserRequest ureq, Controller source, Event event) {
if(source == mediaDialogBox) {
removeAsListenerAndDispose(mediaDialogBox);
removeAsListenerAndDispose(mediaChooserController);
mediaDialogBox = null;
mediaChooserController = null;
} else if (source == mediaChooserController) {
if(event instanceof URLChoosenEvent) {
URLChoosenEvent choosenEvent = (URLChoosenEvent)event;
String url = choosenEvent.getURL();
if(url.startsWith(Settings.getServerContextPathURI())) {
//doesn't allow absolute path -> the mapper check if the link is in the list!
url = url.substring(Settings.getServerContextPathURI().length());
}
currentLink.setTarget(url);
currentLink.setIntern(true);
currentLink.setHtmlTarget(SELF_KEY);
if(StringHelper.containsNonWhitespace(choosenEvent.getDisplayName())) {
currentLink.setDescription(choosenEvent.getDisplayName());
}
int index = 0;
for(TextElement targetEl:lTargetInputList) {
if(currentLink.equals(targetEl.getUserObject())) {
targetEl.setValue(url);
targetEl.setEnabled(false);
lDescriptionInputList.get(index).setValue(currentLink.getDescription());
lHtmlTargetInputList.get(index).select(SELF_KEY, true);
break;
}
index++;
}
}
mediaDialogBox.deactivate();
removeAsListenerAndDispose(mediaDialogBox);
removeAsListenerAndDispose(mediaChooserController);
mediaDialogBox = null;
mediaChooserController = null;
}
super.event(ureq, source, event);
}
/**
* {@inheritDoc}
*/
@Override
protected void initForm(FormItemContainer formLayout, Controller listener, UserRequest ureq) {
// create gui elements for all links
for (int i = 0; i < linkList.size(); i++) {
LLModel link = linkList.get(i);
addNewFormLink(i, link);
}
flc.contextPut("linkList", linkList);
flc.contextPut("lTargetInputList", lTargetInputList);
flc.contextPut("lHtmlTargetInputList", lHtmlTargetInputList);
flc.contextPut("lDescriptionInputList", lDescriptionInputList);
flc.contextPut("lCommentInputList", lCommentInputList);
flc.contextPut("lAddButtonList", lAddButtonList);
flc.contextPut("lDelButtonList", lDelButtonList);
flc.contextPut("lCustomMediaButtonList", lCustomMediaButtonList);
subm = uifactory.addFormSubmitButton("submit", formLayout);
formLayout.add(subm);
}
/**
* Get the module configuration.
*
* @return ModuleConfiguration
*/
public ModuleConfiguration getModuleConfiguration() {
moduleConfig.setConfigurationVersion(2);
return moduleConfig;
}
/**
* Add a new form link line to the list of link elements.
*
* @param link the link model object
*/
private void addNewFormLink(int index, final LLModel link) {
// add link target
TextElement lTarget = uifactory.addTextElement("target" + counter, null, -1, link.getTarget(), flc);
lTarget.setPlaceholderKey("target.example", null);
lTarget.clearError();
lTarget.setEnabled(!link.isIntern());
lTarget.setDisplaySize(40);
lTarget.setMandatory(true);
lTarget.setNotEmptyCheck("ll.table.target.error");
lTarget.setItemValidatorProvider(new ItemValidatorProvider() {
public boolean isValidValue(String value, ValidationError validationError, Locale locale) {
try {
if (!value.contains("://")) {
value = "http://".concat(value);
}
new URL(value);
} catch (MalformedURLException e) {
validationError.setErrorKey("ll.table.target.error.format");
return false;
}
return true;
}
});
lTarget.addActionListener(FormEvent.ONCHANGE);
lTarget.setUserObject(link);
lTargetInputList.add(index, lTarget);
//add html target
SingleSelection htmlTargetSelection = uifactory.addDropdownSingleselect("html_target" + counter, flc, new String[]{BLANK_KEY, SELF_KEY}, new String[]{translate("ll.table.html_target"), translate("ll.table.html_target.self")}, null);
htmlTargetSelection.setUserObject(link);
htmlTargetSelection.select((SELF_KEY.equals(link.getHtmlTarget()) ? SELF_KEY : BLANK_KEY), true);
lHtmlTargetInputList.add(index, htmlTargetSelection);
// add link description
TextElement lDescription = uifactory.addTextElement("description" + counter, null, -1, link.getDescription(), flc);
lDescription.clearError();
lDescription.setDisplaySize(20);
lDescription.setNotEmptyCheck("ll.table.description.error");
lDescription.setMandatory(true);
lDescription.setPlaceholderKey("ll.table.description", null);
lDescription.setUserObject(link);
lDescriptionInputList.add(index, lDescription);
// add link comment
TextElement lComment =uifactory.addTextAreaElement("comment" + counter, null, -1, 2, 50, true, link.getComment(), flc);
lComment.setPlaceholderKey("ll.table.comment", null);
lComment.setDisplaySize(20);
lComment.setUserObject(link);
lCommentInputList.add(index, lComment);
// add link add action button
FormLink addButton = new FormLinkImpl("add" + counter, "add" + counter, "", Link.BUTTON_SMALL + Link.NONTRANSLATED);
addButton.setUserObject(link);
addButton.setDomReplacementWrapperRequired(false);
addButton.setIconLeftCSS("o_icon o_icon-lg o_icon-fw o_icon_add");
flc.add(addButton);
lAddButtonList.add(index, addButton);
// add link deletion action button
FormLink delButton = new FormLinkImpl("delete" + counter, "delete" + counter, "", Link.BUTTON_SMALL + Link.NONTRANSLATED);
delButton.setUserObject(link);
delButton.setDomReplacementWrapperRequired(false);
delButton.setIconLeftCSS("o_icon o_icon-lg o_icon-fw o_icon_delete_item");
flc.add(delButton);
lDelButtonList.add(index, delButton);
// custom media action button
FormLink mediaButton = new FormLinkImpl("media" + counter, "media" + counter, " ", Link.NONTRANSLATED);
mediaButton.setIconLeftCSS("o_icon o_icon_browse o_icon-lg");
mediaButton.setDomReplacementWrapperRequired(false);
mediaButton.setUserObject(link);
flc.add(mediaButton);
lCustomMediaButtonList.add(index, mediaButton);
// increase the counter to enable unique component names
counter++;
}
private void removeFormLink(final LLModel link) {
// remove link from model list
linkList.remove(link);
// remove link gui elements
int i;
for (i = 0; i < lTargetInputList.size(); i++) {
if (lTargetInputList.get(i).getUserObject().equals(link)) {
break;
}
}
flc.remove(lTargetInputList.remove(i));
for (i = 0; i < lHtmlTargetInputList.size(); i++) {
if (lHtmlTargetInputList.get(i).getUserObject().equals(link)) {
break;
}
}
flc.remove(lHtmlTargetInputList.remove(i));
for (i = 0; i < lDescriptionInputList.size(); i++) {
if (lDescriptionInputList.get(i).getUserObject().equals(link)) {
break;
}
}
flc.remove(lDescriptionInputList.remove(i));
for (i = 0; i < lCommentInputList.size(); i++) {
if (lCommentInputList.get(i).getUserObject().equals(link)) {
break;
}
}
flc.remove(lCommentInputList.remove(i));
for (i = 0; i < lAddButtonList.size(); i++) {
if (lAddButtonList.get(i).getUserObject().equals(link)) {
break;
}
}
flc.remove(lAddButtonList.remove(i));
for (i = 0; i < lDelButtonList.size(); i++) {
if (lDelButtonList.get(i).getUserObject().equals(link)) {
break;
}
}
flc.remove(lDelButtonList.remove(i));
for (i = 0; i < lCustomMediaButtonList.size(); i++) {
if (lCustomMediaButtonList.get(i).getUserObject().equals(link)) {
break;
}
}
flc.remove(lCustomMediaButtonList.remove(i));
}
}