///////////////////////////////////////////////////////////////////////////// // // 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 org.apache.wicket.AttributeModifier; import org.apache.wicket.Component; import org.apache.wicket.MarkupContainer; import org.apache.wicket.markup.html.WebMarkupContainer; import org.apache.wicket.markup.html.basic.Label; import org.apache.wicket.markup.html.form.ListMultipleChoice; import org.apache.wicket.markup.html.form.TextField; import org.apache.wicket.markup.repeater.RepeatingView; import org.apache.wicket.model.IModel; import org.apache.wicket.model.Model; import org.apache.wicket.model.ResourceModel; import org.projectforge.web.CSSColor; import org.projectforge.web.wicket.WicketUtils; import org.projectforge.web.wicket.bootstrap.GridPanel; import org.projectforge.web.wicket.components.JiraIssuesPanel; /** * 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 class FieldsetPanel extends AbstractFieldsetPanel<FieldsetPanel> { public static final String FIELD_SET_CLASS = "control-group"; public static final String LABEL_SUFFIX_ID = "labelSuffix"; public static final String DESCRIPTION_SUFFIX_ID = "descriptionSuffix"; private static final long serialVersionUID = -6318707656650110365L; private final WebMarkupContainer controls; private RepeatingView iconContainer; private Label feedbackMessageLabel; private String feedbackMessage; private Component labelSuffix, descriptionSuffix; private boolean initialized; private int childCounter = 0; /** * Adds this FieldsetPanel to the parent panel. * @param parent * @param label */ public FieldsetPanel(final DivPanel parent, final FieldProperties< ? > fieldProperties) { this(parent, getString(parent, fieldProperties.getLabel()), // getString(parent, fieldProperties.getLabelDescription(), fieldProperties.isTranslateLabelDecsription())); } private static String getString(final Component parent, final String label) { return getString(parent, label, true); } private static String getString(final Component parent, final String label, final boolean translate) { if (translate == false || label == null) { return label; } return parent.getString(label); } /** * Adds this FieldsetPanel to the parent panel. * @param parent * @param label */ public FieldsetPanel(final DivPanel parent, final String label) { this(parent, label, null); } /** * Adds this FieldsetPanel to the parent panel. * @param parent * @param label * @param description Description below or beside the label of the field-set. */ public FieldsetPanel(final DivPanel parent, final String labelText, final String description) { this(parent.newChildId(), labelText, description); parent.add(this); } /** * Adds this FieldsetPanel to the parent panel. * @param parent * @param label * @param description Description below or beside the label of the field-set. */ public FieldsetPanel(final GridPanel parent, final String labelText) { this(parent.newChildId(), labelText); parent.add(this); } /** */ public FieldsetPanel(final String id, final String labeltext) { this(id, labeltext, null); } /** * @param id * @param labeltext If null, then the label field is invisible. * @param description */ @SuppressWarnings("serial") public FieldsetPanel(final String id, final String labeltext, final String description) { super(id); this.labelText = labeltext; fieldset = new WebMarkupContainer("fieldset"); superAdd(fieldset); fieldset.add(AttributeModifier.append("class", FIELD_SET_CLASS)); fieldset.add((label = new WebMarkupContainer("label"))); if (labelText != null) { label.add(new Label("labeltext", new Model<String>() { @Override public String getObject() { return labelText; }; }).setRenderBodyOnly(true)); if (description != null) { label.add(new Label("labeldescription", description)); } else { label.add(WicketUtils.getInvisibleComponent("labeldescription")); } } else { label.setVisible(false); } fieldset.add(controls = new WebMarkupContainer("controls")); controls.add(feedbackMessageLabel = new Label("feedbackMessage", new Model<String>() { /** * @see org.apache.wicket.model.Model#getObject() */ @Override public String getObject() { return feedbackMessage; } }) { /** * @see org.apache.wicket.Component#isVisible() */ @Override public boolean isVisible() { return feedbackMessage != null; } }); fieldsRepeater = new RepeatingView("fields"); controls.add(fieldsRepeater); } /** * Please note: only labelSide=false is supported and shouldn't be called twice. The label is placed above the input fields. Default is * labelSide = true. * @param labelSide */ public FieldsetPanel setLabelSide(final boolean labelSide) { if (labelSide == false) { fieldset.add(AttributeModifier.append("class", "vertical")); } return this; } /** * @param labelSuffix the labelSuffix to set * @return this for chaining. */ public FieldsetPanel setLabelSuffix(final Component labelSuffix) { this.labelSuffix = labelSuffix; label.add(labelSuffix); return this; } /** * @param descriptionSuffix the descriptionSuffix to set * @return this for chaining. */ public FieldsetPanel setDescriptionSuffix(final Component descriptionSuffix) { this.descriptionSuffix = descriptionSuffix; label.add(descriptionSuffix); return this; } /** * No wrap of the multiple children. * @return this for chaining. */ public FieldsetPanel setNowrap() { // fieldDiv.add(AttributeModifier.append("style", "white-space: nowrap;")); return this; } /** * @see org.projectforge.web.wicket.flowlayout.AbstractFieldsetPanel#modifyAddedChild(org.apache.wicket.Component) */ @Override protected void modifyAddedChild(final Component child) { if (child instanceof InputPanel) { final InputPanel inputPanel = (InputPanel) child; if (inputPanel.getField() instanceof TextField) { inputPanel.getField().add(AttributeModifier.append("class", "text")); } } } /** * @param id * @param label * @param listChoice * @return The created ListMultipleChoicePanel. * @see ListMultipleChoicePanel#ListMultipleChoicePanel(String, String, ListMultipleChoice) */ public <T> ListMultipleChoicePanel<T> add(final ListMultipleChoice<T> listChoice) { final ListMultipleChoicePanel<T> listChoicePanel = new ListMultipleChoicePanel<T>(newChildId(), listChoice); listChoicePanel.getListMultipleChoice().setLabel(new Model<String>(getLabel())); add(listChoicePanel); return listChoicePanel; } /** * @return The Wicket id of the embedded text fiel of {@link ListMultipleChoicePanel}. */ public String getListChoiceId() { return ListMultipleChoicePanel.WICKET_ID; } /** * @param model * @param labelString * @return The created CheckBoxPanel. * @see CheckBoxPanel#CheckBoxPanel(String, IModel, String) */ public CheckBoxPanel addCheckBox(final IModel<Boolean> model, final String labelString) { return addCheckBox(model, labelString, null); } /** * @param model * @param labelString * @return The created CheckBoxPanel. * @see CheckBoxPanel#CheckBoxPanel(String, IModel, String) */ public CheckBoxPanel addCheckBox(final IModel<Boolean> model, final String labelString, final String tooltip) { final CheckBoxPanel checkBox = new CheckBoxPanel(newChildId(), model, labelString); if (tooltip != null) { checkBox.setTooltip(tooltip); } add(checkBox); return checkBox; } /** * Adds an alert icon at the top left corner of the field set label. * @param tooltip * @return this for chaining. */ public FieldsetPanel addAlertIcon(final String tooltip) { final IconPanel icon = WicketUtils.getAlertTooltipIcon(this, new ResourceModel("common.attention"), Model.of(tooltip)); add(icon, FieldSetIconPosition.TOP_LEFT); return this; } /** * Adds a help icon at the top right corner of the field set. * @param title * @param tooltip * @return The created IconPanel. */ public IconPanel addHelpIcon(final IModel<String> title, final IModel<String> tooltip) { return addHelpIcon(title, tooltip, FieldSetIconPosition.TOP_RIGHT); } /** * Adds a help icon at the top right corner of the field set. * @param title * @param tooltip * @param iconPosition * @return The created IconPanel. */ public IconPanel addHelpIcon(final IModel<String> title, final IModel<String> tooltip, final FieldSetIconPosition iconPosition) { final IconPanel icon = new IconPanel(newIconChildId(), IconType.HELP, title, tooltip).setColor(CSSColor.GRAY); add(icon, iconPosition); return icon; } /** * Adds a help icon at the top right corner of the field set. * @param tooltip * @return The created IconPanel. */ public IconPanel addHelpIcon(final String tooltip) { return addHelpIcon(tooltip, FieldSetIconPosition.TOP_RIGHT); } /** * Adds a help icon at the top right corner of the field set. * @param tooltip * @return The created IconPanel. */ public IconPanel addHelpIcon(final String tooltip, final FieldSetIconPosition iconPosition) { final IconPanel icon = new IconPanel(newIconChildId(), IconType.HELP, tooltip).setColor(CSSColor.GRAY); add(icon, iconPosition); return icon; } /** * Adds a help icon at the top right corner of the field set. * @param tooltip * @return The created IconPanel. */ public IconPanel addHelpIcon(final IModel<String> tooltip) { final IconPanel icon = new IconPanel(newIconChildId(), IconType.HELP, tooltip).setColor(CSSColor.GRAY); add(icon, FieldSetIconPosition.TOP_RIGHT); return icon; } /** * Adds a keyboard icon at the bottom right corner of the field set. * @param tooltip * @return this for chaining. */ public FieldsetPanel addKeyboardHelpIcon(final String tooltip) { return add(new IconPanel(newIconChildId(), IconType.KEYBOARD, tooltip).setColor(CSSColor.GRAY), FieldSetIconPosition.BOTTOM_RIGHT); } /** * Adds a keyboard icon at the bottom right corner of the field set. * @param tooltip * @return this for chaining. */ public FieldsetPanel addKeyboardHelpIcon(final IModel<String> title, final IModel<String> tooltip) { return add(new IconPanel(newIconChildId(), IconType.KEYBOARD, title, tooltip).setColor(CSSColor.GRAY), FieldSetIconPosition.BOTTOM_RIGHT); } /** * Adds a JIRA icon at the bottom right corner of the field set (only if JIRA is configured, otherwise this method does nothing). This * method is automatically called by {@link #addJIRAField()}. * @param tooltip * @return this for chaining. */ public FieldsetPanel addJIRASupportHelpIcon() { if (WicketUtils.isJIRAConfigured() == true) { return add(WicketUtils.getJIRASupportTooltipIcon(this).setColor(CSSColor.GRAY), FieldSetIconPosition.TOP_RIGHT); } else { // No JIRA configured. return this; } } /** * Adds a JIRA icon at the bottom right corner of the field set (only if JIRA is configured, otherwise this method does nothing). * @param tooltip * @return this for chaining. */ public FieldsetPanel addJIRAField(final IModel<String> model) { if (WicketUtils.isJIRAConfigured() == true) { add(new JiraIssuesPanel(newChildId(), model)); add(WicketUtils.getJIRASupportTooltipIcon(this).setColor(CSSColor.GRAY), FieldSetIconPosition.TOP_RIGHT); } return this; } public FieldsetPanel add(final IconPanel icon, final FieldSetIconPosition iconPosition) { icon.getDiv().add(AttributeModifier.append("class", iconPosition.getStyleAttrValue())); if (iconContainer == null) { throw new IllegalArgumentException("No icons container given! May-be you forget to call newIconChildId() before adding an image."); } iconContainer.add(icon).setRenderBodyOnly(true); return this; } public String newIconChildId() { if (iconContainer == null) { iconContainer = new RepeatingView("icons"); fieldset.add(iconContainer); } return iconContainer.newChildId(); } /** * @return the feedbackMessage */ public Label getFeedbackMessageLabel() { return feedbackMessageLabel; } /** * @param feedbackMessage * @return this for chaining. */ public FieldsetPanel setFeedbackMessage(final String feedbackMessage) { this.feedbackMessage = feedbackMessage; return this; } /** * Creates and add a new RepeatingView as div-child if not already exist. * @see RepeatingView#newChildId() */ @Override public String newChildId() { if (childCounter++ == 1) { controls.add(AttributeModifier.append("class", "controls-row")); } return fieldsRepeater.newChildId(); } public FieldsetPanel removeAllFields() { fieldsRepeater.removeAll(); return this; } public FieldsetPanel setDivStyle(final DivType divType) { this.controls.add(AttributeModifier.append("class", divType.getClassAttrValue())); return this; } public DivPanel addNewCheckBoxButtonDiv() { final DivPanel checkBoxDiv = new DivPanel(newChildId(), DivType.BTN_GROUP); add(checkBoxDiv); return checkBoxDiv; } public DivPanel addNewRadioBoxButtonDiv() { final DivPanel radioBoxDiv = new DivPanel(newChildId(), DivType.BTN_GROUP); add(radioBoxDiv); return radioBoxDiv; } /** * @see org.projectforge.web.wicket.flowlayout.AbstractFieldsetPanel#onBeforeRender() */ @Override protected void onBeforeRender() { if (initialized == false) { // Can't be done in onInitialize() because this component is added to its parent in constructor and onInitialize() is some times // called before the setter methods (e. g. for labelSide) are called. initialized = true; if (labelSuffix == null) { label.add(labelSuffix = WicketUtils.getInvisibleComponent("labelSuffix")); } if (descriptionSuffix == null) { label.add(descriptionSuffix = WicketUtils.getInvisibleComponent("descriptionSuffix")); } if (iconContainer == null) { fieldset.add(new WebMarkupContainer("icons").setVisible(false)); } } super.onBeforeRender(); } /** * @see org.projectforge.web.wicket.flowlayout.AbstractFieldsetPanel#addChild(org.apache.wicket.Component[]) */ @Override protected MarkupContainer addChild(final Component... childs) { return controls.add(childs); } public WebMarkupContainer getControlsDiv() { return controls; } /** * @see org.projectforge.web.wicket.flowlayout.AbstractFieldsetPanel#getThis() */ @Override protected FieldsetPanel getThis() { return this; } public boolean hasChilds() { return childCounter > 0; } }