Repository: wicket Updated Branches: refs/heads/master 580d92ddf -> eee7299a0
WICKET-6077 Border's body is not added as a child due to dequeuing Apply the quickstart as a test case to prevent regressions Project: http://git-wip-us.apache.org/repos/asf/wicket/repo Commit: http://git-wip-us.apache.org/repos/asf/wicket/commit/10f360c5 Tree: http://git-wip-us.apache.org/repos/asf/wicket/tree/10f360c5 Diff: http://git-wip-us.apache.org/repos/asf/wicket/diff/10f360c5 Branch: refs/heads/master Commit: 10f360c57a713a054a5cfc63585d8ed5a17409a0 Parents: 803af5d Author: Martin Tzvetanov Grigorov <[email protected]> Authored: Sun Jan 17 10:25:31 2016 +0100 Committer: Martin Tzvetanov Grigorov <[email protected]> Committed: Fri Jan 22 21:37:48 2016 +0100 ---------------------------------------------------------------------- .../wicket/queueing/ComponentQueueingTest.java | 25 ++ .../queueing/bodyisachild/BodyIsAChildPage.html | 22 ++ .../queueing/bodyisachild/BodyIsAChildPage.java | 41 +++ .../wicket/queueing/bodyisachild/FormGroup.html | 15 ++ .../wicket/queueing/bodyisachild/FormGroup.java | 262 +++++++++++++++++++ .../queueing/bodyisachild/LoginPanel.html | 21 ++ .../queueing/bodyisachild/LoginPanel.java | 62 +++++ 7 files changed, 448 insertions(+) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/wicket/blob/10f360c5/wicket-core/src/test/java/org/apache/wicket/queueing/ComponentQueueingTest.java ---------------------------------------------------------------------- diff --git a/wicket-core/src/test/java/org/apache/wicket/queueing/ComponentQueueingTest.java b/wicket-core/src/test/java/org/apache/wicket/queueing/ComponentQueueingTest.java index 4307063..15250df 100644 --- a/wicket-core/src/test/java/org/apache/wicket/queueing/ComponentQueueingTest.java +++ b/wicket-core/src/test/java/org/apache/wicket/queueing/ComponentQueueingTest.java @@ -37,12 +37,15 @@ import org.apache.wicket.markup.html.list.ListView; import org.apache.wicket.markup.html.panel.Fragment; import org.apache.wicket.markup.html.panel.Panel; import org.apache.wicket.model.Model; +import org.apache.wicket.queueing.bodyisachild.BodyIsAChildPage; +import org.apache.wicket.queueing.bodyisachild.LoginPanel; import org.apache.wicket.queueing.nestedborders.InnerBorder; import org.apache.wicket.queueing.nestedborders.OuterBorder; import org.apache.wicket.queueing.nestedpanels.InnerPanel; import org.apache.wicket.queueing.nestedpanels.OuterPanel; import org.apache.wicket.util.resource.IResourceStream; import org.apache.wicket.util.resource.StringResourceStream; +import org.apache.wicket.util.tester.FormTester; import org.apache.wicket.util.tester.WicketTestCase; import org.junit.Assert; import org.junit.Test; @@ -789,6 +792,28 @@ public class ComponentQueueingTest extends WicketTestCase tester.startComponentInPage(p); } + /** + * https://issues.apache.org/jira/browse/WICKET-6077 + */ + @Test + public void bodyIsAChild() { + tester.startPage(BodyIsAChildPage.class); + + tester.assertRenderedPage(BodyIsAChildPage.class); + + String username = "USER"; + String password = "PASSWD"; + + FormTester formTester = tester.newFormTester("wmc:login:loginForm"); + formTester.setValue("usernameFormGroup:usernameFormGroup_body:username", username); + formTester.setValue("passwordFormGroup:passwordFormGroup_body:password", password); + formTester.submit(); + + LoginPanel loginPanel = (LoginPanel) tester.getComponentFromLastRenderedPage("wmc:login"); + assertEquals(username, loginPanel.pojo.username); + assertEquals(password, loginPanel.pojo.password); + } + private static class A extends WebMarkupContainer { public A() http://git-wip-us.apache.org/repos/asf/wicket/blob/10f360c5/wicket-core/src/test/java/org/apache/wicket/queueing/bodyisachild/BodyIsAChildPage.html ---------------------------------------------------------------------- diff --git a/wicket-core/src/test/java/org/apache/wicket/queueing/bodyisachild/BodyIsAChildPage.html b/wicket-core/src/test/java/org/apache/wicket/queueing/bodyisachild/BodyIsAChildPage.html new file mode 100644 index 0000000..4e09162 --- /dev/null +++ b/wicket-core/src/test/java/org/apache/wicket/queueing/bodyisachild/BodyIsAChildPage.html @@ -0,0 +1,22 @@ +<!DOCTYPE html> +<html xmlns:wicket="http://wicket.apache.org"> + <head> + <meta charset="utf-8" /> + <title>Apache Wicket Quickstart</title> + <link href='http://fonts.googleapis.com/css?family=Yanone+Kaffeesatz:regular,bold' rel='stylesheet' type='text/css' /> + <link rel="stylesheet" href="style.css" type="text/css" media="screen" title="Stylesheet" /> + </head> + <body> + <div id="hd"> + <div id="logo"> + <img src="logo.png" width="50px" height="50px" alt="Wicket Logo" /> + <h1>Apache Wicket</h1> + </div> + </div> + <div id="bd"> + <div wicket:id="wmc"> + <div wicket:id="login"></div> + </div> + </div> + </body> +</html> http://git-wip-us.apache.org/repos/asf/wicket/blob/10f360c5/wicket-core/src/test/java/org/apache/wicket/queueing/bodyisachild/BodyIsAChildPage.java ---------------------------------------------------------------------- diff --git a/wicket-core/src/test/java/org/apache/wicket/queueing/bodyisachild/BodyIsAChildPage.java b/wicket-core/src/test/java/org/apache/wicket/queueing/bodyisachild/BodyIsAChildPage.java new file mode 100644 index 0000000..5c69ed5 --- /dev/null +++ b/wicket-core/src/test/java/org/apache/wicket/queueing/bodyisachild/BodyIsAChildPage.java @@ -0,0 +1,41 @@ +/* + * 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.markup.html.WebMarkupContainer; +import org.apache.wicket.markup.html.WebPage; +import org.apache.wicket.request.mapper.parameter.PageParameters; + +public class BodyIsAChildPage extends WebPage +{ + private static final long serialVersionUID = 1L; + + public BodyIsAChildPage(final PageParameters parameters) + { + super(parameters); + } + + @Override + protected void onInitialize() + { + super.onInitialize(); + + WebMarkupContainer wmc = new WebMarkupContainer("wmc"); + wmc.add(new LoginPanel("login")); + add(wmc); + } +} http://git-wip-us.apache.org/repos/asf/wicket/blob/10f360c5/wicket-core/src/test/java/org/apache/wicket/queueing/bodyisachild/FormGroup.html ---------------------------------------------------------------------- diff --git a/wicket-core/src/test/java/org/apache/wicket/queueing/bodyisachild/FormGroup.html b/wicket-core/src/test/java/org/apache/wicket/queueing/bodyisachild/FormGroup.html new file mode 100644 index 0000000..1478378 --- /dev/null +++ b/wicket-core/src/test/java/org/apache/wicket/queueing/bodyisachild/FormGroup.html @@ -0,0 +1,15 @@ +<html xmlns:wicket="http://wicket.apache.org"> + <head> + <title>FormGroup</title> + </head> + <body> + <wicket:border> + <label wicket:id="label" class="control-label">Text input</label> + + <wicket:body/> + + <p wicket:id="error" class="help-block"></p> + <p wicket:id="help" class="help-block">Supporting help text</p> + </wicket:border> + </body> +</html> http://git-wip-us.apache.org/repos/asf/wicket/blob/10f360c5/wicket-core/src/test/java/org/apache/wicket/queueing/bodyisachild/FormGroup.java ---------------------------------------------------------------------- diff --git a/wicket-core/src/test/java/org/apache/wicket/queueing/bodyisachild/FormGroup.java b/wicket-core/src/test/java/org/apache/wicket/queueing/bodyisachild/FormGroup.java new file mode 100644 index 0000000..beaf770 --- /dev/null +++ b/wicket-core/src/test/java/org/apache/wicket/queueing/bodyisachild/FormGroup.java @@ -0,0 +1,262 @@ +/* + * 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(); + } +} http://git-wip-us.apache.org/repos/asf/wicket/blob/10f360c5/wicket-core/src/test/java/org/apache/wicket/queueing/bodyisachild/LoginPanel.html ---------------------------------------------------------------------- diff --git a/wicket-core/src/test/java/org/apache/wicket/queueing/bodyisachild/LoginPanel.html b/wicket-core/src/test/java/org/apache/wicket/queueing/bodyisachild/LoginPanel.html new file mode 100644 index 0000000..60302ec --- /dev/null +++ b/wicket-core/src/test/java/org/apache/wicket/queueing/bodyisachild/LoginPanel.html @@ -0,0 +1,21 @@ +<!DOCTYPE html> +<html xmlns="http://www.w3.org/1999/xhtml" xmlns:wicket="http://wicket.apache.org"> +<body> +<wicket:panel> + Login + <form class="form_style" wicket:id="loginForm"> + <div class="form-group" wicket:id="usernameFormGroup"> + <div class="input-group"> + <input id="username" type="text" class="form-control user" wicket:id="username"> + </div> + </div> + <div class="form-group" wicket:id="passwordFormGroup"> + <div class="input-group"> + <input id="password" type="password" class="form-control password" wicket:id="password"> + </div> + </div> + <button>LOGIN</button> + </form> +</wicket:panel> +</body> +</html> http://git-wip-us.apache.org/repos/asf/wicket/blob/10f360c5/wicket-core/src/test/java/org/apache/wicket/queueing/bodyisachild/LoginPanel.java ---------------------------------------------------------------------- diff --git a/wicket-core/src/test/java/org/apache/wicket/queueing/bodyisachild/LoginPanel.java b/wicket-core/src/test/java/org/apache/wicket/queueing/bodyisachild/LoginPanel.java new file mode 100644 index 0000000..a8a3792 --- /dev/null +++ b/wicket-core/src/test/java/org/apache/wicket/queueing/bodyisachild/LoginPanel.java @@ -0,0 +1,62 @@ +/* + * 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.markup.html.form.FormComponent; +import org.apache.wicket.markup.html.form.PasswordTextField; +import org.apache.wicket.markup.html.form.StatelessForm; +import org.apache.wicket.markup.html.form.TextField; +import org.apache.wicket.markup.html.panel.Panel; +import org.apache.wicket.model.CompoundPropertyModel; +import org.apache.wicket.model.Model; + +import java.io.Serializable; + +public class LoginPanel extends Panel +{ + public final Pojo pojo = new Pojo(); + + public LoginPanel(String id) + { + super(id); + add(new LoginForm("loginForm")); + } + + public static class Pojo implements Serializable + { + public String username; + public String password; + } + + class LoginForm extends StatelessForm { + + public LoginForm(String id) { + super(id); + setModel(new CompoundPropertyModel<>(pojo)); + add(createValidatingFormField(new TextField("username").setRequired(true), "yourUsernameHeadline")); + add(createValidatingFormField(new PasswordTextField("password").setResetPassword(false), "yourPasswordHeadline")); + } + + private FormGroup createValidatingFormField(final FormComponent formComponent, String labelKey) { + final String fieldId = formComponent.getId(); + final FormGroup formGroup = new FormGroup(fieldId + "FormGroup", Model.of(labelKey)); + formGroup.setOutputMarkupId(true); + formGroup.add(formComponent); + return formGroup; + } + } +}
