///////////////////////////////////////////////////////////////////////////// // // Project ProjectForge Community Edition // www.projectforge.org // // Copyright (C) 2001-2014 Kai Reinhard (k.reinhard@micromata.de) // // ProjectForge is dual-licensed. // // This community edition is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as published // by the Free Software Foundation; version 3 of the License. // // This community edition is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General // Public License for more details. // // You should have received a copy of the GNU General Public License along // with this program; if not, see http://www.gnu.org/licenses/. // ///////////////////////////////////////////////////////////////////////////// package org.projectforge.web.wicket.flowlayout; import java.util.ArrayList; import java.util.List; import org.apache.wicket.AttributeModifier; import org.apache.wicket.Component; import org.apache.wicket.MarkupContainer; import org.apache.wicket.extensions.ajax.markup.html.AjaxEditableLabel; import org.apache.wicket.extensions.markup.html.form.select.Select; import org.apache.wicket.feedback.FeedbackMessage; import org.apache.wicket.markup.html.WebMarkupContainer; import org.apache.wicket.markup.html.form.DropDownChoice; import org.apache.wicket.markup.html.form.FormComponent; import org.apache.wicket.markup.html.form.IChoiceRenderer; import org.apache.wicket.markup.html.form.LabeledWebMarkupContainer; import org.apache.wicket.markup.html.form.PasswordTextField; import org.apache.wicket.markup.html.form.TextArea; import org.apache.wicket.markup.html.form.TextField; import org.apache.wicket.markup.html.panel.Panel; import org.apache.wicket.markup.repeater.RepeatingView; import org.apache.wicket.model.IModel; import org.apache.wicket.model.Model; import org.projectforge.common.StringHelper; import org.projectforge.web.WebConfiguration; import org.projectforge.web.wicket.WebConstants; import org.projectforge.web.wicket.WicketUtils; import com.vaynberg.wicket.select2.Select2MultiChoice; /** * Represents a entry of a group panel. This can be a label, text field or other form components. * @author Kai Reinhard (k.reinhard@micromata.de) * */ public abstract class AbstractFieldsetPanel<T extends AbstractFieldsetPanel< ? >> extends Panel { private static final long serialVersionUID = -4215154959282166107L; private static final org.apache.log4j.Logger log = org.apache.log4j.Logger.getLogger(AbstractFieldsetPanel.class); protected WebMarkupContainer fieldset; protected WebMarkupContainer label; protected boolean labelFor; protected String labelText; protected RepeatingView fieldsRepeater; private final List<FormComponent< ? >> allFormComponents = new ArrayList<FormComponent< ? >>(); private Object storeObject; /** * Adds this FieldsetPanel to the parent panel. * @param parent * @param label */ protected AbstractFieldsetPanel(final String id) { super(id); } public T setUnit(final String unit) { this.labelText = WicketUtils.getLabelWithUnit(labelText, unit); return getThis(); } /** * @return the labelText */ public String getLabel() { return labelText; } /** * Sets the background color of this whole fieldset to red. * @return this for chaining. */ public T setWarningBackground() { fieldset.add(AttributeModifier.replace("style", WebConstants.CSS_BACKGROUND_COLOR_RED)); return getThis(); } public T setLabelFor(final Component component) { if (component instanceof ComponentWrapperPanel) { this.label.add(AttributeModifier.replace("for", ((ComponentWrapperPanel) component).getComponentOutputId())); } else { this.label.add(AttributeModifier.replace("for", component.getMarkupId())); } labelFor = true; return getThis(); } /** * Declares that there is no validation field which the label should set for. This has no other meaning and effect than not to display the * development warning "No label set for field...'. * @return */ public T suppressLabelForWarning() { labelFor = true; return getThis(); } public Component superAdd(final Component... childs) { return super.add(childs); } /** * @see org.apache.wicket.MarkupContainer#add(org.apache.wicket.Component[]) */ @Override public MarkupContainer add(final Component... childs) { checkLabelFor(childs); for (final Component component : childs) { modifyAddedChild(component); addFormComponent(component); } return fieldsRepeater.add(childs); } private void addFormComponent(final Component component) { if (component instanceof FormComponent< ? >) { this.allFormComponents.add((FormComponent< ? >) component); } else if (component instanceof ComponentWrapperPanel) { final FormComponent< ? > fc = ((ComponentWrapperPanel) component).getFormComponent(); if (fc != null) { this.allFormComponents.add(fc); } } } /** * Checks all child form components and calls {@link FormComponent#isValid()}. * @return true if all childs are valid, otherwise false (if any child is invalid); */ public boolean isValid() { for (final FormComponent< ? > formComponent : allFormComponents) { if (formComponent.isValid() == false) { return false; } } return true; } /** * @return true if any form child has a feedback message. * @see org.apache.wicket.Component#hasFeedbackMessage() */ public boolean hasFormChildsFeedbackMessage() { for (final FormComponent< ? > formComponent : allFormComponents) { if (formComponent.hasFeedbackMessage() == true) { return true; } } return false; } public String getFormChildsFeedbackMessages(final boolean markAsRendered) { if (hasFormChildsFeedbackMessage() == false) { return null; } final StringBuffer buf = new StringBuffer(); boolean first = true; for (final FormComponent< ? > formComponent : allFormComponents) { if (formComponent.hasFeedbackMessage() == true) { final FeedbackMessage feedbackMessage = formComponent.getFeedbackMessages().first(); if (markAsRendered == true) { feedbackMessage.markRendered(); } first = StringHelper.append(buf, first, feedbackMessage.getMessage().toString(), "\n"); } } return buf.toString(); } /** * @param textField * @return The created InputPanel. * @see InputPanel#InputPanel(String, Component) */ public InputPanel add(final TextField< ? > textField) { final InputPanel input = new InputPanel(newChildId(), textField); add(input); return input; } /** * @param textField * @return The created InputPanel. * @see InputPanel#InputPanel(String, Component) */ public InputPanel add(final TextField< ? > textField, final FieldProperties< ? > fieldProperties) { final InputPanel input = add(textField); if (fieldProperties.getFieldType() != null) { setFieldType(input, fieldProperties.getFieldType()); } return input; } protected InputPanel setFieldType(final InputPanel input, final FieldType fieldType) { input.setFieldType(fieldType); return input; } /** * @param passwordField * @return The created PasswordPanel. * @see PasswordPanel#PasswordPanel(String, Component) */ public PasswordPanel add(final PasswordTextField passwordField) { final PasswordPanel passwordInput = new PasswordPanel(newChildId(), passwordField); add(passwordInput); return passwordInput; } /** * @return The Wicket id of the embedded text field of InputPanel */ public final String getTextFieldId() { return InputPanel.WICKET_ID; } /** * @param textArea * @return The created InputPanel. * @see TextAreaPanel#TextAreaPanel(String, Component) */ public TextAreaPanel add(final TextArea< ? > textArea) { return add(textArea, false); } /** * @param textArea * @return The created InputPanel. * @see TextAreaPanel#TextAreaPanel(String, Component) */ public TextAreaPanel add(final TextArea< ? > textArea, final boolean autogrow) { final TextAreaPanel panel = new TextAreaPanel(newChildId(), textArea, autogrow); add(panel); return panel; } /** * @return The Wicket id of the embedded text field of TextAreaPanel */ public final String getTextAreaId() { return TextAreaPanel.WICKET_ID; } /** * @param id * @param label * @param model * @param values * @param renderer * @return The created DropDownChoicePanel. * @see DropDownChoicePanel#DropDownChoicePanel(String, String, IModel, List, IChoiceRenderer) */ public <C> DropDownChoicePanel<C> addDropDownChoice(final IModel<C> model, final List< ? extends C> values, final IChoiceRenderer<C> renderer) { return addDropDownChoice(model, values, renderer, false); } /** * @param id * @param label * @param model * @param values * @param renderer * @param submitOnChange. * @return The created DropDownChoicePanel. * @see DropDownChoicePanel#DropDownChoicePanel(String, String, IModel, List, IChoiceRenderer, boolean)) */ public <C> DropDownChoicePanel<C> addDropDownChoice(final IModel<C> model, final List< ? extends C> values, final IChoiceRenderer<C> renderer, final boolean submitOnChange) { final DropDownChoicePanel<C> dropDownChoicePanel = new DropDownChoicePanel<C>(newChildId(), model, values, renderer, submitOnChange); add(dropDownChoicePanel); return dropDownChoicePanel; } /** * @param id * @param label * @param dropDownChoice * @return The created DropDownChoicePanel. * @see DropDownChoicePanel#DropDownChoicePanel(String, String, DropDownChoice) */ public <C> DropDownChoicePanel<C> add(final DropDownChoice<C> dropDownChoice) { return add(dropDownChoice, false); } /** * @param id * @param label * @param dropDownChoice * @return The created DropDownChoicePanel. * @see DropDownChoicePanel#DropDownChoicePanel(String, String, DropDownChoice, boolean) */ public <C> DropDownChoicePanel<C> add(final DropDownChoice<C> dropDownChoice, final boolean submitOnChange) { final DropDownChoicePanel<C> dropDownChoicePanel = new DropDownChoicePanel<C>(newChildId(), dropDownChoice, submitOnChange); add(dropDownChoicePanel); return dropDownChoicePanel; } /** * @return The Wicket id of the embedded select field of {@link DropDownChoicePanel}. */ public String getDropDownChoiceId() { return DropDownChoicePanel.WICKET_ID; } /** * @param id * @param select * @return The created SelectPanel. * @see SelectPanel#SelectPanel(String, Select) */ public <C> SelectPanel<C> add(final Select<C> select) { final SelectPanel<C> selectPanel = new SelectPanel<C>(newChildId(), select); add(selectPanel); return selectPanel; } /** * @return The Wicket id of the embedded select field of {@link DropDownChoicePanel}. */ public String getSelectId() { return SelectPanel.WICKET_ID; } /** * @param id * @param ajaxEditableLabel * @return The created AjaxEditableLabelPanel. * @see SelectPanel#SelectPanel(String, Select) */ public <C> AjaxEditableLabelPanel<C> add(final AjaxEditableLabel<C> ajaxEditableLabel) { final AjaxEditableLabelPanel<C> ajaxEditableLabelPanel = new AjaxEditableLabelPanel<C>(newChildId(), ajaxEditableLabel); add(ajaxEditableLabelPanel); return ajaxEditableLabelPanel; } /** * @return The Wicket id of the embedded select field of {@link DropDownChoicePanel}. */ public String getAjaxEditableLabelId() { return AjaxEditableLabelPanel.WICKET_ID; } public <C> Select2MultiChoicePanel<C> add(final Select2MultiChoice<C> select2MultiChoice) { final Select2MultiChoicePanel<C> select2MultiChoicePanel = new Select2MultiChoicePanel<C>(newChildId(), select2MultiChoice); add(select2MultiChoicePanel); return select2MultiChoicePanel; } /** * @return The Wicket id of the embedded text fiel of {@link DropDownChoicePanel}. */ public String getSelect2MultiChoiceId() { return Select2MultiChoicePanel.WICKET_ID; } public abstract String newChildId(); protected void modifyAddedChild(final Component child) { } protected abstract MarkupContainer addChild(Component... childs); private void checkLabelFor(final Component... components) { if (labelFor == true) { return; } final Component component = components[0]; if (component instanceof ComponentWrapperPanel) { this.label.add(AttributeModifier.replace("for", ((ComponentWrapperPanel) component).getComponentOutputId())); labelFor = true; } for (final Component comp : components) { if (comp instanceof LabeledWebMarkupContainer) { final LabeledWebMarkupContainer labeledComponent = (LabeledWebMarkupContainer) comp; if (labeledComponent.getLabel() == null) { labeledComponent.setLabel(new Model<String>(labelText)); } } else if (component instanceof ComponentWrapperPanel) { final FormComponent<?> formComponent = ((ComponentWrapperPanel)component).getFormComponent(); if (formComponent != null && formComponent.getLabel() == null) { formComponent.setLabel(new Model<String>(labelText)); } } } } /** * @see org.apache.wicket.Component#onBeforeRender() */ @Override protected void onBeforeRender() { if (labelFor == false && WebConfiguration.isDevelopmentMode() == true) { log.warn("No label set for field '" + labelText + "'. Please call setLabelFor(component) for this fieldset or supressLabelForWarning()."); } super.onBeforeRender(); } protected abstract T getThis(); /** * Can be used by e. g. TimesheetPageSupport for storing objects, used by the supported form. * @param storeObject the childField to set * @return this for chaining. */ public T setStoreObject(final Object storeObject) { this.storeObject = storeObject; return getThis(); } /** * Can be used by e. g. TimesheetPageSupport for storing objects, used by the supported form. * @return the childField */ public Object getStoreObject() { return storeObject; } /** * @return the fieldset */ public WebMarkupContainer getFieldset() { return fieldset; } }