/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.wicket.queueing.bodyisachild;
import org.apache.wicket.AttributeModifier;
import org.apache.wicket.Component;
import org.apache.wicket.feedback.FeedbackMessage;
import org.apache.wicket.feedback.FeedbackMessages;
import org.apache.wicket.markup.ComponentTag;
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.markup.html.border.Border;
import org.apache.wicket.markup.html.form.FormComponent;
import org.apache.wicket.model.IModel;
import org.apache.wicket.model.LoadableDetachableModel;
import org.apache.wicket.model.Model;
import org.apache.wicket.util.string.Strings;
import org.apache.wicket.util.visit.IVisit;
import org.apache.wicket.util.visit.IVisitor;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
* Simplified copy from Wicket-Bootstrap
*/
public class FormGroup extends Border
{
private Component label;
private Component help;
private Component feedback;
private String stateClassName;
private final IModel<String> labelModel;
private final IModel<String> helpModel;
/**
* Construct.
*
* @param id the wicket component id
* @param label the label
*/
public FormGroup(final String id, final IModel<String> label)
{
this(id, label, Model.of(""));
}
/**
* Construct.
*
* @param id the wicket component id
*/
public FormGroup(final String id, final IModel<String> label, final IModel<String> help)
{
super(id, Model.of(""));
this.labelModel = label;
this.helpModel = help;
this.stateClassName = "";
}
/**
* creates a new label
*
* @param id the component id
* @param model the content model for this component
* @return new label
*/
protected Component newLabel(final String id, final IModel<String> model)
{
return new Label(id, model);
}
/**
* creates a new container for a feedback message
*
* @param id the component id
* @return new feedback message container
*/
protected Component newFeedbackMessageContainer(final String id)
{
return new Label(id, new Model<String>());
}
/**
* creates a new help label that contains a help message for the form field. This field
* will be set to invisible if there is no content.
*
* @param id the component id
* @param model the content model for this component
* @return new help label
*/
protected Component newHelpLabel(final String id, final IModel<String> model)
{
return new Label(id, model);
}
@Override
protected void onComponentTag(ComponentTag tag)
{
super.onComponentTag(tag);
checkComponentTag(tag, "div");
tag.append("class", "form-group", " ");
tag.append("class", stateClassName, " ");
}
@Override
protected void onInitialize()
{
super.onInitialize();
this.label = newLabel("label", labelModel);
this.help = newHelpLabel("help", helpModel);
this.feedback = newFeedbackMessageContainer("error");
addToBorder(this.label, this.help, this.feedback);
final List<FormComponent<?>> formComponents = findFormComponents();
final int size = formComponents.size();
if (size > 0)
{
addOutputMarkupId(formComponents);
final FormComponent<?> formComponent = formComponents.get(size - 1);
label.add(new AttributeModifier("for", formComponent.getMarkupId()));
final boolean useFormComponentLabel = true;
if (useFormComponentLabel)
{
label.setDefaultModel(new LoadableDetachableModel<String>()
{
@Override
protected String load() {
if (formComponent.getLabel() != null && !Strings.isEmpty(formComponent.getLabel().getObject()))
{
return formComponent.getLabel().getObject();
}
else
{
String text = formComponent.getDefaultLabel("wicket:unknown");
if (!"wicket:unknown".equals(text) && !Strings.isEmpty(text))
{
return text;
}
else
{
return labelModel.getObject();
}
}
}
});
}
}
}
/**
* sets the output markup id flag to true for all given formComponents. This is necessary to
* reference them in a "for" attribute on client side.
*
* @param formComponents the form components to add the output markup id
*/
protected void addOutputMarkupId(List<FormComponent<?>> formComponents)
{
for (final FormComponent<?> fc : formComponents)
{
fc.setOutputMarkupId(true);
}
}
@Override
protected void onConfigure()
{
super.onConfigure();
// set all components visible
help.setVisible(true);
label.setVisible(true);
feedback.setVisible(true);
// clear feedback message and current state
stateClassName = "";
feedback.setDefaultModelObject("");
final List<FormComponent<?>> formComponents = findFormComponents();
for (final FormComponent<?> fc : formComponents)
{
final FeedbackMessages messages = fc.getFeedbackMessages();
if (!messages.isEmpty())
{
final FeedbackMessage worstMessage = getWorstMessage(messages);
worstMessage.markRendered();
feedback.setDefaultModelObject(worstMessage.getMessage());
break; // render worst message of first found child component with feedback message
}
}
}
/**
* @return all form components that are assigned to this {@link FormGroup}
*/
List<FormComponent<?>> findFormComponents()
{
final List<FormComponent<?>> components = new ArrayList<>();
getBodyContainer().visitChildren(FormComponent.class, new IVisitor<FormComponent, Void>()
{
@Override
public void component(FormComponent formComponent, IVisit<Void> visit)
{
components.add(formComponent);
}
});
return components;
}
/**
* ordered list of all feedback message types.
*/
private static final List<Integer> messageTypes = Arrays.asList(
FeedbackMessage.FATAL, FeedbackMessage.ERROR, FeedbackMessage.WARNING, FeedbackMessage.SUCCESS,
FeedbackMessage.INFO, FeedbackMessage.DEBUG, FeedbackMessage.UNDEFINED
);
/**
* returns the worst message that is available.
*
* @param messages all current feedback messages
* @return worst possible message or null
*/
private FeedbackMessage getWorstMessage(final FeedbackMessages messages)
{
for (final Integer messageType : messageTypes)
{
final FeedbackMessage ret = messages.first(messageType);
if (ret != null)
{
return ret;
}
}
return messages.first();
}
}