/** * 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. * <p> */ package org.olat.core.gui.components.form.flexible.impl; import java.util.List; import java.util.Locale; import org.olat.core.CoreSpringFactory; import org.olat.core.commons.services.help.HelpModule; import org.olat.core.gui.UserRequest; import org.olat.core.gui.components.Component; import org.olat.core.gui.components.form.flexible.FormBaseComponentIdProvider; import org.olat.core.gui.components.form.flexible.FormItem; import org.olat.core.gui.components.form.flexible.FormLayouter; import org.olat.core.gui.components.form.flexible.elements.InlineElement; import org.olat.core.gui.components.form.flexible.impl.components.SimpleExampleText; import org.olat.core.gui.components.form.flexible.impl.components.SimpleFormErrorText; import org.olat.core.gui.components.form.flexible.impl.components.SimpleLabelText; import org.olat.core.gui.components.panel.Panel; import org.olat.core.gui.translator.Translator; import org.olat.core.helpers.Settings; import org.olat.core.logging.AssertException; import org.olat.core.util.ValidationStatus; /** * <h2>Description:</h2> * <P> * Initial Date: 22.11.2006 <br> * * @author patrickb */ public abstract class FormItemImpl implements FormItem, InlineElement { private static final String PREFIX = "PANEL_"; private boolean componentIsMandatory; private String errorKey; private String[] errorParams; private Component errorComponent; private Panel errorPanel; private String[] exampleParams; private String exampleKey; private String[] helpParams; private String helpKey; private String helpText; private String helpUrl; private Component exampleC; private Panel examplePanel; private String[] labelParams; private String labelKey; private boolean translateLabel; private Component labelC; private Panel labelPanel; protected Translator translator; private final String id; private String name; private boolean hasLabel = false; private boolean hasExample = false; protected boolean hasError = false; private Form rootForm = null; protected int action; private Object userObject; private boolean hasFocus = false; private boolean formItemIsEnabled = true; private boolean isInlineEditingElement; private boolean isInlineEditingOn; private Component inlineEditingComponent; private String i18nKey4EmptyText="inline.empty.click.for.edit"; private String elementCssClass; /** * * @param name */ public FormItemImpl(String name) { this(name, false);//default is not inline } public FormItemImpl(String name, boolean asInlineEditingElement) { this(null, name, asInlineEditingElement); } public FormItemImpl(String id, String name, boolean asInlineEditingElement) { this.id = id; this.name = name; this.isInlineEditingElement = asInlineEditingElement; /* * prepare three panels as placeholder for label, example, error */ errorPanel = new Panel(PREFIX + name + FormItem.ERRORC); examplePanel = new Panel(PREFIX + name + FormItem.EXAMPLEC); labelPanel = new Panel(PREFIX + name + FormItem.LABELC); } @Override public String getFormItemId() { return id; } @Override public String getForId() { return getFormDispatchId(); } @Override public String getName() { return name; } @Override public String getElementCssClass() { return elementCssClass; } @Override public void setElementCssClass(String elementCssClass) { this.elementCssClass = elementCssClass; } @Override public boolean isInlineEditingOn() { if(!isInlineEditingElement) throw new AssertException("isInlineEditingOn called although it is not a inlineEditingElement"); return isInlineEditingOn; } @Override public FormItem setEmptyDisplayText(String i18nKey4Text) { this.i18nKey4EmptyText = i18nKey4Text; return this; } public String getEmptyDisplayText(){ if(getTranslator()==null) throw new AssertException("getEmptyDisplayText called to early, no translator available"); return translate(i18nKey4EmptyText, null); } protected void isInlineEditingOn(boolean isOn){ if(!isInlineEditingElement) throw new AssertException("isInlineEditingOn(..) called although it is not a inlineEditingElement"); isInlineEditingOn = isOn; } protected Component getInlineEditingComponent(){ if(!isInlineEditingElement) throw new AssertException("getInlineEditingComponent called although it is not a inlineEditingElement"); return inlineEditingComponent; } protected void setInlineEditingComponent(Component inlineEditingComponent){ if(!isInlineEditingElement) throw new AssertException("getInlineEditingComponent called although it is not a inlineEditingElement"); this.inlineEditingComponent = inlineEditingComponent; } @Override public boolean isInlineEditingElement(){ return isInlineEditingElement; } /** * @see org.olat.core.gui.components.form.flexible.FormComponent#getAsComponent() */ public Component getComponent(){ // return isInlineEditingElement ? getInlineEditingComponent() : getFormItemComponent(); } protected abstract Component getFormItemComponent(); /** * @see org.olat.core.gui.components.form.flexible.FormComponent#getRootForm() */ public Form getRootForm() { return rootForm; } public void setRootForm(Form rootForm){ this.rootForm = rootForm; rootFormAvailable(); } protected abstract void rootFormAvailable(); protected boolean translateLabel() { return translateLabel; } public void setTranslator(Translator translator) { this.translator = translator; //(re)translate label, error, example //typically setTranslator is called form parent container if the FormItem //is added. String labelTrsl = translateLabel() ? translate(labelKey, labelParams) : labelKey; if(Settings.isDebuging()){ //in develmode, check that either translation for labelkey is available //or that the other method to add the element is used. //other in the sense of using the LabelI18nKey set to null, this //avoids false messages in the logfile concering missng translations. if(labelTrsl == null && hasLabel()){ throw new AssertException("Your label "+labelKey+" for formitem "+getName()+" is not available, please use the addXXX method with labelI18nKey and set it to null."); } } if(labelKey != null) { labelC = new SimpleLabelText(this, labelKey, labelTrsl); labelC.setTranslator(translator); labelPanel.setContent(labelC); } if(errorKey != null) { errorComponent = new SimpleFormErrorText(errorKey, translate(errorKey, errorParams)); errorPanel.setContent(errorComponent); } if(exampleKey != null) { exampleC = new SimpleExampleText(exampleKey, translate(exampleKey, exampleParams)); examplePanel.setContent(exampleC); } if(helpKey != null) { helpText = translate(helpKey, helpParams); } } public Translator getTranslator() { return translator; } public Component getLabelC() { return labelPanel; } public String getLabelText() { return translateLabel() ? translate(labelKey, labelParams) : labelKey; } public void setLabel(String label, String[] params) { setLabel(label, params, true); } public void setLabel(String label, String[] params, boolean translate) { hasLabel = (label != null); translateLabel = translate; labelKey = label; labelParams = params; // set label may be called before the translator is available if (getTranslator() != null && labelKey != null) { labelC = new SimpleLabelText(this, label, getLabelText()); labelC.setTranslator(getTranslator()); labelPanel.setContent(labelC); } else if(label == null) { labelC = null; labelPanel.setContent(labelC); } } public void setFocus(boolean hasFocus){ this.hasFocus = hasFocus; } public boolean isMandatory() { return componentIsMandatory; } public boolean hasFocus(){ return hasFocus; } public void setMandatory(boolean isMandatory) { componentIsMandatory = isMandatory; } /** * @see org.olat.core.gui.components.form.flexible.FormComponent#getExample() */ public Component getExampleC() { return examplePanel; } /** * @see org.olat.core.gui.components.form.flexible.FormComponent#getExampleText() */ public String getExampleText() { return translate(exampleKey, exampleParams); } /** * @see org.olat.core.gui.components.form.flexible.FormComponent#getHelpText() */ public String getHelpText() { // always translated return helpText; } /** * @see org.olat.core.gui.components.form.flexible.FormComponent#getHelpUrl() */ public String getHelpUrl() { return helpUrl; } /** * @see org.olat.core.gui.components.form.flexible.FormComponent#setExampleKey(java.lang.String, * java.lang.String[]) */ public void setExampleKey(String exampleKey, String[] params) { hasExample = true; this.exampleKey = exampleKey; this.exampleParams = params; if (getTranslator() != null) { exampleC = new SimpleExampleText(exampleKey, translate(exampleKey, params)); examplePanel.setContent(exampleC); } else if(exampleKey == null) { exampleC = null; examplePanel.setContent(exampleC); } } /** * @see org.olat.core.gui.components.form.flexible.FormComponent#setHelpTextKey(java.lang.String, * java.lang.String[]) */ public void setHelpTextKey(String helpKey, String[] params) { this.helpKey = helpKey; this.helpParams = params; if (getTranslator() != null) { this.helpText = translate(helpKey, helpParams); } } /** * @see org.olat.core.gui.components.form.flexible.FormComponent#setHelpText(java.lang.String) */ public void setHelpText(String helpText) { this.helpKey = null; this.helpParams = null; this.helpText = helpText; } /** * @see org.olat.core.gui.components.form.flexible.FormComponent#setHelpUrl(java.lang.String) */ public void setHelpUrl(String helpUrl) { this.helpUrl = helpUrl; } /** * @see org.olat.core.gui.components.form.flexible.FormComponent#setHelpUrlForManualPage(java.lang.String) */ public void setHelpUrlForManualPage(String manualAliasName) { HelpModule helpModule = CoreSpringFactory.getImpl(HelpModule.class); Locale locale = getTranslator().getLocale(); this.helpUrl = helpModule.getHelpProvider().getURL(locale, manualAliasName); } /** * @see org.olat.core.gui.components.form.flexible.FormComponent#setErrorKey(java.lang.String, * java.lang.String[]) */ public void setErrorKey(String errorKey, String[] params) { this.hasError = true; this.errorKey = errorKey; this.errorParams = params; if (getTranslator() != null) { errorComponent = new SimpleFormErrorText(errorKey, translate(errorKey, errorParams)); errorPanel.setContent(errorComponent); } showError(hasError); getRootForm().getInitialComponent().setDirty(true); } /** * convenience * * @param key * @param params * @return */ private String translate(String key, String[] params) { String retVal = null; if (key != null && params != null) { retVal = translator.translate(key, params); } else if (key != null) { retVal = translator.translate(key); } return retVal; } /** * @see org.olat.core.gui.components.form.flexible.FormComponent#setErrorController(org.olat.core.gui.control.Controller) */ public void setErrorComponent(FormItem errorFormItem, FormLayouter container) { if(errorFormItem == null){ throw new AssertException("do not clear error by setting null, instead use showError(false)."); } //initialize root form of form item FormLayoutContainer flc = (FormLayoutContainer)container;//TODO:pb: fix this hierarchy mismatch flc.register(errorFormItem);//errorFormItem must be part of the composite chain, that it gets dispatched hasError = true; errorComponent = errorFormItem.getComponent(); errorPanel.setContent(errorComponent); } /** * @see org.olat.core.gui.components.form.flexible.FormComponent#getErrorController() */ public Component getErrorC() { return errorPanel; } public void setEnabled(boolean isEnabled) { getErrorC().setEnabled(isEnabled); if(errorComponent != null) { errorComponent.setEnabled(isEnabled); } getExampleC().setEnabled(isEnabled); if(exampleC!=null) { exampleC.setEnabled(isEnabled); } getLabelC().setEnabled(isEnabled); if(labelC!=null) { labelC.setEnabled(isEnabled); } formItemIsEnabled = isEnabled; if(getComponent()==null) return; getComponent().setEnabled(isEnabled); } public boolean isEnabled(){ return formItemIsEnabled; } public void setVisible(boolean isVisible) { //FIXME:pb: getComponent can be null in the case of FormLink for example if(getComponent()==null) return; getComponent().setVisible(isVisible); showError(isVisible && hasError); showExample(isVisible && hasExample); showLabel(isVisible && hasLabel); } public boolean isVisible() { if(getComponent() == null) return false; return getComponent().isVisible(); } public boolean hasError(){ return hasError; } public boolean hasLabel(){ return hasLabel; } public boolean hasExample(){ return hasExample; } public void showLabel(boolean show){ if(show) { labelPanel.setContent(labelC); }else{ labelPanel.setContent(null); } labelPanel.setVisible(show); labelPanel.setEnabled(show); } public void showError(boolean show){ if (show) { errorPanel.setContent(errorComponent); }else{ errorPanel.setContent(null); } errorPanel.setVisible(show); errorPanel.setEnabled(show); } public void clearError(){ showError(false); hasError = false; } public void showExample(boolean show){ if(show) { examplePanel.setContent(exampleC); }else{ examplePanel.setContent(null); } examplePanel.setVisible(show); examplePanel.setEnabled(show); } /** * @see org.olat.core.gui.components.form.flexible.FormItem#addActionListenerFor(org.olat.core.gui.control.Controller, int) */ @Override public void addActionListener(int action) { this.action = action; } @Override public int getAction() { return action; } /** * gets called if the implementing component is part of a form which gets * partly submitted -> extract data for you and store it temporarly for * redisplay without a validation * * @param ureq */ public abstract void evalFormRequest(UserRequest ureq); /** * gets called if the implementing component was clicked. * * @param ureq * @param formId */ public void doDispatchFormRequest(UserRequest ureq){ //first let implementor do its job dispatchFormRequest(ureq); if(getRootForm().hasAlreadyFired()){ //dispatchFormRequest did fire already //in this case we do not try to fire the general events return; } //before/ after pattern switch (getRootForm().getAction()) { case FormEvent.ONCLICK: getRootForm().fireFormEvent(ureq, new FormEvent("ONCLICK", this, FormEvent.ONCLICK)); break; case FormEvent.ONDBLCLICK: getRootForm().fireFormEvent(ureq, new FormEvent("ONDBLCLICK", this, FormEvent.ONDBLCLICK)); break; case FormEvent.ONCHANGE: getRootForm().fireFormEvent(ureq, new FormEvent("ONCHANGE", this, FormEvent.ONCHANGE)); break; default: //nothing to do, default is handled } } /** * @see org.olat.core.gui.components.form.flexible.api.FormItem#getUserObject() */ public Object getUserObject() { return userObject; } /** * @see org.olat.core.gui.components.form.flexible.api.FormItem#setUserObject(java.lang.Object) */ public void setUserObject(Object userObject) { this.userObject = userObject; } /** * */ public String getFormDispatchId() { Component comp = getComponent(); if(comp instanceof FormBaseComponentIdProvider){ return ((FormBaseComponentIdProvider)comp).getFormDispatchId(); } else { //do the same as the FormBaseComponentIdProvider would do return DISPPREFIX.concat(comp.getDispatchID()); } } /** * override to implement your behaviour * @param ureq */ protected void dispatchFormRequest(UserRequest ureq){ //default implementation does nothing } /** * @see org.olat.core.gui.components.form.flexible.FormComponent#validate(java.util.List) */ public void validate(List<ValidationStatus> validationResults) { } /** * @see org.olat.core.gui.components.form.flexible.FormItem#reset() */ public abstract void reset(); @Override public String toString(){ return "FoItem:"+getName()+ "[ena:"+isEnabled()+ ", vis:"+isVisible()+ ", err:"+hasError()+ ", exa:"+hasExample()+ ", lab:"+hasLabel(); } }