package org.sigmah.client.ui.widget.form;
/*
* #%L
* Sigmah
* %%
* Copyright (C) 2010 - 2016 URD
* %%
* This program 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, either version 3 of the
* License, or (at your option) any later version.
*
* This program 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/gpl-3.0.html>.
* #L%
*/
import java.util.Date;
import org.sigmah.client.dispatch.DispatchAsync;
import org.sigmah.client.i18n.I18N;
import org.sigmah.client.ui.widget.button.Button;
import org.sigmah.client.ui.widget.button.SplitButton;
import org.sigmah.client.util.ClientUtils;
import com.extjs.gxt.ui.client.Style.HorizontalAlignment;
import com.extjs.gxt.ui.client.Style.Orientation;
import com.extjs.gxt.ui.client.data.ModelData;
import com.extjs.gxt.ui.client.event.ButtonEvent;
import com.extjs.gxt.ui.client.event.Events;
import com.extjs.gxt.ui.client.event.FieldEvent;
import com.extjs.gxt.ui.client.event.Listener;
import com.extjs.gxt.ui.client.event.SelectionListener;
import com.extjs.gxt.ui.client.store.ListStore;
import com.extjs.gxt.ui.client.widget.form.AdapterField;
import com.extjs.gxt.ui.client.widget.form.CheckBox;
import com.extjs.gxt.ui.client.widget.form.CheckBoxGroup;
import com.extjs.gxt.ui.client.widget.form.ComboBox;
import com.extjs.gxt.ui.client.widget.form.ComboBox.TriggerAction;
import com.extjs.gxt.ui.client.widget.form.DateField;
import com.extjs.gxt.ui.client.widget.form.FileUploadField;
import com.extjs.gxt.ui.client.widget.form.FormPanel.LabelAlign;
import com.extjs.gxt.ui.client.widget.form.FormPanel.Method;
import com.extjs.gxt.ui.client.widget.form.HiddenField;
import com.extjs.gxt.ui.client.widget.form.LabelField;
import com.extjs.gxt.ui.client.widget.form.NumberField;
import com.extjs.gxt.ui.client.widget.form.Radio;
import com.extjs.gxt.ui.client.widget.form.RadioGroup;
import com.extjs.gxt.ui.client.widget.form.SimpleComboBox;
import com.extjs.gxt.ui.client.widget.form.TextArea;
import com.extjs.gxt.ui.client.widget.form.TextField;
import com.extjs.gxt.ui.client.widget.form.Time;
import com.extjs.gxt.ui.client.widget.form.TimeField;
import com.extjs.gxt.ui.client.widget.layout.FormData;
import com.extjs.gxt.ui.client.widget.layout.FormLayout;
import com.extjs.gxt.ui.client.widget.menu.Menu;
import com.extjs.gxt.ui.client.widget.menu.MenuItem;
import com.google.gwt.event.logical.shared.AttachEvent;
import com.google.gwt.i18n.client.NumberFormat;
import com.google.gwt.user.client.ui.AbstractImagePrototype;
import com.google.gwt.user.client.ui.IsWidget;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.ScrollPanel;
import com.google.gwt.user.client.ui.UIObject;
import com.google.gwt.user.client.ui.Widget;
import org.sigmah.client.ui.res.icon.IconImageBundle;
import org.sigmah.shared.dto.element.FlexibleElementContainer;
import org.sigmah.shared.dto.layout.LayoutGroupDTO;
/**
* <p>
* Forms utility class providing utility methods for forms.
* </p>
* <p>
* Useful default values:
* <ul>
* <li><b>Form padding:</b> 10px (see {@link #DEFAULT_PADDING}).</li>
* <li><b>Label width:</b> 100px (see {@link #DEFAULT_LABEL_WIDTH}).</li>
* <li><b>Field width:</b> 250px (see {@link #DEFAULT_FIELD_WIDTH}).</li>
* </ul>
* </p>
*
* @author Denis Colliot (dcolliot@ideia.fr)
* @see org.sigmah.client.ui.widget.form.FormPanel
*/
public final class Forms {
/**
* <p>
* Default forms fields width (in pixels).
* </p>
* <p>
* Instead of specifying field width manually, use {@link #data()} to generate a {@code 100%} width.
* </p>
*/
private static final int DEFAULT_FIELD_WIDTH = 250;
/**
* Default forms padding (in pixels).
*/
private static final int DEFAULT_PADDING = 10;
/**
* <p>
* Default forms panels right padding (in pixels).
* This specific right padding is used to properly display fields error icons.
* </p>
*/
static final int DEFAULT_RIGHT_PADDING = 25;
/**
* CSS style name of the headers.
*/
private static final String STYLE_FORM_HEADER_LABEL = "form-header-label";
/**
* Builds a new {@link org.sigmah.client.ui.widget.form.FormPanel} with default {@link FormLayout}.
*
* @param stylenames
* (optional) Style names added to the panel component.
* {@code null} values are ignored.
* @return The {@link org.sigmah.client.ui.widget.form.FormPanel} instance.
*/
public static org.sigmah.client.ui.widget.form.FormPanel panel(final String... stylenames) {
return panel(null, false, null, null, stylenames);
}
/**
* Builds a new {@link org.sigmah.client.ui.widget.form.FormPanel} with default {@link FormLayout}.
*
* @param labelWidth
* The width of the form fields labels.
* @param stylenames
* (optional) Style names added to the panel component.
* {@code null} values are ignored.
* @return The {@link org.sigmah.client.ui.widget.form.FormPanel} instance.
*/
public static org.sigmah.client.ui.widget.form.FormPanel panel(final Integer labelWidth, final String... stylenames) {
return panel(null, false, labelWidth, null, stylenames);
}
/**
* Builds a new {@link org.sigmah.client.ui.widget.form.FormPanel} with default {@link FormLayout}.
*
* @param labelWidth
* The width of the form fields labels.
* @param fieldWidth
* The width of the form fields. Set a default value if {@code null}.
* @param stylenames
* (optional) Style names added to the panel component.
* {@code null} values are ignored.
* @return The {@link org.sigmah.client.ui.widget.form.FormPanel} instance.
*/
public static org.sigmah.client.ui.widget.form.FormPanel panel(final Integer labelWidth, final Integer fieldWidth, final String... stylenames) {
return panel(null, false, labelWidth, fieldWidth, stylenames);
}
/**
* Builds a new {@link org.sigmah.client.ui.widget.form.FormPanel} with default {@link FormLayout}.
*
* @param title
* The panel header title (html is supported).
* If {@code null}, header is disabled and automatically hidden.
* @param collapsible
* {@code true} to set the panel collapsible (expand/collapse toggle button).
* @param labelWidth
* The width of the form fields labels.
* @param fieldWidth
* The width of the form fields. Set a default value if {@code null}.
* @param stylenames
* (optional) Style names added to the panel component.
* {@code null} values are ignored.
* @return The {@link org.sigmah.client.ui.widget.form.FormPanel} instance.
*/
public static org.sigmah.client.ui.widget.form.FormPanel panel(final String title, final boolean collapsible, final Integer labelWidth,
final Integer fieldWidth, final String... stylenames) {
final org.sigmah.client.ui.widget.form.FormPanel panel = new org.sigmah.client.ui.widget.form.FormPanel();
panel.setLayout(layout(labelWidth, fieldWidth, stylenames));
panel.setHeadingHtml(ClientUtils.isNotBlank(title) ? title : null);
panel.setHeaderVisible(ClientUtils.isNotBlank(title));
panel.setCollapsible(collapsible);
panel.setMethod(Method.POST);
panel.setFieldWidth(fieldWidth != null ? fieldWidth : DEFAULT_FIELD_WIDTH);
panel.setButtonAlign(HorizontalAlignment.RIGHT);
panel.setPadding(DEFAULT_PADDING);
if (ClientUtils.isNotEmpty(stylenames)) {
for (final String stylename : stylenames) {
if (ClientUtils.isBlank(stylename)) {
continue;
}
panel.addStyleName(stylename);
}
}
return panel;
}
/**
* Builds a new {@link org.sigmah.client.ui.widget.form.IterableGroupPanel}.
*
* @param title
* The panel header title (html is supported).
* If {@code null}, header is disabled and automatically hidden.
* @param stylenames
* (optional) Style names added to the panel component.
* {@code null} values are ignored.
* @return The {@link org.sigmah.client.ui.widget.form.IterableGroupPanel} instance.
*/
public static org.sigmah.client.ui.widget.form.IterableGroupPanel iterableGroupPanel(DispatchAsync dispatch,
final LayoutGroupDTO layoutGroup,
FlexibleElementContainer container,
final boolean canEdit,
final String... stylenames) {
final org.sigmah.client.ui.widget.form.IterableGroupPanel panel = new org.sigmah.client.ui.widget.form.IterableGroupPanel(dispatch, layoutGroup, container, canEdit);
String title = layoutGroup.getTitle();
panel.setTitle(ClientUtils.isNotBlank(title) ? title : null);
if (ClientUtils.isNotEmpty(stylenames)) {
for (final String stylename : stylenames) {
if (ClientUtils.isBlank(stylename)) {
continue;
}
panel.addStyleName(stylename);
}
}
return panel;
}
// --------------------------------------------------------------------------------
//
// LAYOUT.
//
// --------------------------------------------------------------------------------
/**
* Default forms labels width (in pixels).
*/
private static final int DEFAULT_LABEL_WIDTH = 100;
/**
* Default space between forms labels and fields (in pixels).
*/
private static final int DEFAULT_LABEL_PAD = 5;
/**
* Builds a new {@link FormLayout}.
*
* @param labelWidth
* The width of the form fields labels. Set a default value if {@code null}.
* @param fieldWidth
* The width of the form fields. Set a default value if {@code null}.
* @param stylenames
* (optional) Style names added to the layout.
* {@code null} values are ignored.
* @return The {@link FormLayout} instance.
*/
public static FormLayout layout(final Integer labelWidth, final Integer fieldWidth, final String... stylenames) {
final FormLayout layout = new FormLayout() {
@Override
protected void initTarget() {
super.initTarget();
target.addStyleName(stylenames);
}
};
layout.setLabelWidth(labelWidth != null ? labelWidth : DEFAULT_LABEL_WIDTH);
layout.setDefaultWidth(fieldWidth != null ? fieldWidth : DEFAULT_FIELD_WIDTH);
layout.setLabelPad(DEFAULT_LABEL_PAD);
layout.setLabelSeparator(I18N.CONSTANTS.form_label_separator());
layout.setLabelAlign(LabelAlign.LEFT);
return layout;
}
/**
* Builds a new {@link FormData} configured with width {@code 100%}.
*
* @return The {@link FormData} instance.
*/
public static FormData data() {
return new FormData("100%");
}
// --------------------------------------------------------------------------------
//
// HEADERS.
//
// --------------------------------------------------------------------------------
/**
* Builds a new form header label widget.
*
* @param label
* The form header label.
* @return A new form header label widget.
*/
public static Widget header(String label) {
final Label headerLabel = new Label(label);
headerLabel.setStyleName(STYLE_FORM_HEADER_LABEL);
return headerLabel;
}
// --------------------------------------------------------------------------------
//
// FIELDS.
//
// --------------------------------------------------------------------------------
// --
// -- TextField
// --
/**
* Builds a {@link TextField}.
*
* @param label
* The field label.
* @param mandatory
* <code>true</code> if the field doesn't allow blanks, <code>false</code> otherwise.
* @param stylenames
* (optional) Style name(s) added to the field. Blank values are ignored.
* @return The field.
*/
public static <D> TextField<D> text(String label, boolean mandatory, String... stylenames) {
return text(label, mandatory, null, stylenames);
}
/**
* Builds a {@link TextField}.
*
* @param label
* The field label.
* @param mandatory
* <code>true</code> if the field doesn't allow blanks, <code>false</code> otherwise.
* @param maxLength
* Max length of the value.
* @param stylenames
* (optional) Style name(s) added to the field. Blank values are ignored.
* @return The field.
*/
public static <D> TextField<D> text(String label, boolean mandatory, Integer maxLength, String... stylenames) {
final TextField<D> field = new TextField<D>();
// Label.
if (ClientUtils.isNotBlank(label)) {
field.setFieldLabel(label);
}
// Constraints.
field.setAllowBlank(!mandatory);
if (maxLength != null) {
maxLength = maxLength >= 0 ? maxLength : 0;
field.setMaxLength(maxLength);
}
return addStyles(field, stylenames);
}
// --
// -- TextArea
// --
/**
* Builds a {@link TextArea}.
*
* @param label
* The field label.
* @param mandatory
* <code>true</code> if the field doesn't allow blanks, <code>false</code> otherwise.
* @param stylenames
* (optional) Style name(s) added to the field. Blank values are ignored.
* @return The field.
*/
public static TextArea textarea(String label, boolean mandatory, String... stylenames) {
return textarea(label, mandatory, null, stylenames);
}
/**
* Builds a {@link TextArea}.
*
* @param label
* The field label.
* @param mandatory
* <code>true</code> if the field doesn't allow blanks, <code>false</code> otherwise.
* @param maxLength
* Max length of the value.
* @param stylenames
* (optional) Style name(s) added to the field. Blank values are ignored.
* @return The field.
*/
public static TextArea textarea(String label, boolean mandatory, Integer maxLength, String... stylenames) {
final TextArea field = new TextArea();
// Label.
if (ClientUtils.isNotBlank(label)) {
field.setFieldLabel(label);
}
// Constraints.
field.setAllowBlank(!mandatory);
if (maxLength != null) {
maxLength = maxLength >= 0 ? maxLength : 0;
field.setMaxLength(maxLength);
}
return addStyles(field, stylenames);
}
// --
// -- NumberField
// --
/**
* Builds a {@link NumberField}.
*
* @param label
* The field label.
* @param mandatory
* <code>true</code> if the field doesn't allow blanks, <code>false</code> otherwise.
* @param stylenames
* (optional) Style name(s) added to the field. Blank values are ignored.
* @return The field.
*/
public static NumberField number(String label, boolean mandatory, String... stylenames) {
return number(label, mandatory, true, stylenames);
}
/**
* Builds a {@link NumberField}.
*
* @param label
* The field label.
* @param mandatory
* <code>true</code> if the field doesn't allow blanks, <code>false</code> otherwise.
* @param allowNegative
* Sets whether negative value are allowed.
* @param stylenames
* (optional) Style name(s) added to the field. Blank values are ignored.
* @return The field.
*/
public static NumberField number(String label, boolean mandatory, boolean allowNegative, String... stylenames) {
return number(label, mandatory, allowNegative, true, stylenames);
}
/**
* Builds a {@link NumberField}.
*
* @param label
* The field label.
* @param mandatory
* <code>true</code> if the field doesn't allow blanks, <code>false</code> otherwise.
* @param allowNegative
* Sets whether negative value are allowed.
* @param allowDecimals
* Sets whether decimal value are allowed.
* @param stylenames
* (optional) Style name(s) added to the field. Blank values are ignored.
* @return The field.
*/
public static NumberField number(String label, boolean mandatory, boolean allowNegative, boolean allowDecimals, String... stylenames) {
return number(label, mandatory, allowNegative, allowDecimals, null, stylenames);
}
/**
* Builds a {@link NumberField}.
*
* @param label
* The field label.
* @param mandatory
* <code>true</code> if the field doesn't allow blanks, <code>false</code> otherwise.
* @param allowNegative
* Sets whether negative value are allowed.
* @param allowDecimals
* Sets whether decimal value are allowed.
* @param format
* The number format.
* @param stylenames
* (optional) Style name(s) added to the field. Blank values are ignored.
* @return The field.
*/
public static NumberField number(String label, boolean mandatory, boolean allowNegative, boolean allowDecimals, final NumberFormat format,
String... stylenames) {
final NumberField field = new NumberField();
// Label.
if (ClientUtils.isNotBlank(label)) {
field.setFieldLabel(label);
}
// Format.
if (format != null) {
field.setFormat(format);
field.addListener(Events.Blur, new Listener<FieldEvent>() {
@Override
public void handleEvent(FieldEvent be) {
final Number value = field.getValue();
field.setFormat(format);
field.setValue(value);
}
});
field.addListener(Events.Focus, new Listener<FieldEvent>() {
@Override
public void handleEvent(FieldEvent be) {
final Number value = field.getValue();
field.setFormat(null);
field.setValue(value);
}
});
}
// Constraints.
field.setAllowBlank(!mandatory);
field.setAllowNegative(allowNegative);
field.setAllowDecimals(allowDecimals);
return addStyles(field, stylenames);
}
// --
// -- LabelField
// --
/**
* Builds a {@link LabelField}.
*
* @param label
* The field label (automatically includes proper form label separator).
* @param stylenames
* (optional) Style name(s) added to the field. Blank values are ignored.
* @return The field.
*/
public static LabelField label(String label, String... stylenames) {
final LabelField field = new LabelField();
// Label.
if (ClientUtils.isNotBlank(label)) {
// Note: GXT does not set a form label separator on LabelField (?).
field.setFieldLabel(label + I18N.CONSTANTS.form_label_separator());
}
return addStyles(field, stylenames);
}
// --
// -- ComboBox
// --
/**
* Builds a {@link ComboBox} with a default empty {@link ListStore} and default {@link TriggerAction#ALL}.<br>
* Generated field is not editable by default.
*
* @param label
* The field label.
* @param mandatory
* <code>true</code> if the field doesn't allow blanks, <code>false</code> otherwise.
* @param valueField
* The value field name.
* @param displayField
* The display field.
* @param stylenames
* (optional) Style name(s) added to the field. Blank values are ignored.
* @return The field.
*/
public static <D extends ModelData> ComboBox<D> combobox(String label, boolean mandatory, String valueField, String displayField, String... stylenames) {
return combobox(label, mandatory, valueField, displayField, null, null, stylenames);
}
/**
* Builds a {@link ComboBox} with default {@link TriggerAction#ALL}.<br>
* Generated field is not editable by default.
*
* @param label
* The field label.
* @param mandatory
* <code>true</code> if the field doesn't allow blanks, <code>false</code> otherwise.
* @param valueField
* The value field name.
* @param displayField
* The display field.
* @param store
* The values store.
* @param stylenames
* (optional) Style name(s) added to the field. Blank values are ignored.
* @return The field.
*/
public static <D extends ModelData> ComboBox<D> combobox(String label, boolean mandatory, String valueField, String displayField, ListStore<D> store,
String... stylenames) {
return combobox(label, mandatory, valueField, displayField, null, store, stylenames);
}
/**
* Builds a {@link ComboBox} with default {@link TriggerAction#ALL}.<br>
* Generated field is not editable by default.
*
* @param label
* The field label.
* @param mandatory
* <code>true</code> if the field doesn't allow blanks, <code>false</code> otherwise.
* @param valueField
* The value field name.
* @param displayField
* The display field.
* @param emptyText
* The empty text. If blank, a default empty text is set.
* @param store
* The values store. If {@code null}, an empty {@link ListStore} is set.
* @param stylenames
* (optional) Style name(s) added to the field. Blank values are ignored.
* @return The field.
*/
public static <D extends ModelData> ComboBox<D> combobox(String label, boolean mandatory, String valueField, String displayField, String emptyText,
ListStore<D> store, String... stylenames) {
final ComboBox<D> field = new ComboBox<D>();
field.setTriggerAction(TriggerAction.ALL);
field.setEditable(false);
// Label.
if (ClientUtils.isNotBlank(label)) {
field.setFieldLabel(label);
}
if (ClientUtils.isNotBlank(emptyText)) {
field.setEmptyText(emptyText);
} else {
field.setEmptyText(I18N.CONSTANTS.formWindowListEmptyText());
}
// Value.
field.setValueField(valueField);
field.setDisplayField(displayField);
// Store.
field.setStore(store != null ? store : new ListStore<D>());
// Constraints.
field.setAllowBlank(!mandatory);
return addStyles(field, stylenames);
}
// --
// -- SimpleComboBox
// --
/**
* Builds a {@link SimpleComboBox} with default {@link TriggerAction#ALL}.<br>
* Generated field is not editable by default.
*
* @param label
* The field label.
* @param mandatory
* <code>true</code> if the field doesn't allow blanks, <code>false</code> otherwise.
* @param stylenames
* (optional) Style name(s) added to the field. Blank values are ignored.
* @return The field.
*/
public static <T> SimpleComboBox<T> simpleCombobox(String label, boolean mandatory, String... stylenames) {
return simpleCombobox(label, mandatory, null, stylenames);
}
/**
* Builds a {@link SimpleComboBox} with default {@link TriggerAction#ALL}.<br>
* Generated field is not editable by default.
*
* @param label
* The field label.
* @param mandatory
* <code>true</code> if the field doesn't allow blanks, <code>false</code> otherwise.
* @param emptyText
* The empty text. If blank, a default empty text is set.
* @param stylenames
* (optional) Style name(s) added to the field. Blank values are ignored.
* @return The field.
*/
public static <T> SimpleComboBox<T> simpleCombobox(String label, boolean mandatory, String emptyText, String... stylenames) {
final SimpleComboBox<T> field = new SimpleComboBox<T>();
field.setTriggerAction(TriggerAction.ALL);
field.setEditable(false);
// Label.
if (ClientUtils.isNotBlank(label)) {
field.setFieldLabel(label);
}
if (ClientUtils.isNotBlank(emptyText)) {
field.setEmptyText(emptyText);
} else {
field.setEmptyText(I18N.CONSTANTS.formWindowListEmptyText());
}
// Constraints.
field.setAllowBlank(!mandatory);
return addStyles(field, stylenames);
}
// --
// -- Radio / RadioGroup
// --
/**
* Builds a {@link Radio}.
*
* @param boxLabel
* The field <b>radio</b> label.
* @param stylenames
* (optional) Style name(s) added to the field. Blank values are ignored.
* @return The field.
*/
public static Radio radio(String boxLabel, String... stylenames) {
return radio(boxLabel, null, null, stylenames);
}
/**
* Builds a {@link Radio}.
*
* @param boxLabel
* The field <b>radio</b> label.
* @param value
* The field value ({@code null} means {@code false}).
* @param stylenames
* (optional) Style name(s) added to the field. Blank values are ignored.
* @return The field.
*/
public static Radio radio(String boxLabel, Boolean value, String... stylenames) {
return radio(boxLabel, null, value, stylenames);
}
/**
* Builds a {@link Radio}.
*
* @param boxLabel
* The field <b>radio</b> label.
* @param name
* The radio field name property (recommended for {@link RadioGroup} fields).
* @param value
* The field value ({@code null} means {@code false}).
* @param stylenames
* (optional) Style name(s) added to the field. Blank values are ignored.
* @return The field.
*/
public static Radio radio(String boxLabel, String name, Boolean value, String... stylenames) {
return radio(boxLabel, name, null, value, stylenames);
}
/**
* Builds a {@link Radio}.
*
* @param boxLabel
* The field <b>radio</b> label.
* @param name
* The radio field name property (recommended for {@link RadioGroup} fields).
* @param fieldLabel
* The field label.
* @param value
* The field value ({@code null} means {@code false}).
* @param stylenames
* (optional) Style name(s) added to the field. Blank values are ignored.
* @return The field.
*/
public static Radio radio(String boxLabel, String name, String fieldLabel, Boolean value, String... stylenames) {
final Radio field = new Radio();
if (ClientUtils.isNotBlank(boxLabel)) {
field.setBoxLabel(boxLabel);
}
if (ClientUtils.isNotBlank(name)) {
field.setName(name);
}
if (ClientUtils.isNotBlank(fieldLabel)) {
field.setFieldLabel(fieldLabel);
}
field.setValue(value);
return addStyles(field, stylenames);
}
/**
* Builds a {@link RadioGroup} with auto-generated name property and default horizontal orientation.
*
* @param label
* The field label.
* @param radios
* The {@link Radio} fields that belong to the group.
* @return The field.
*/
public static RadioGroup radioGroup(String label, Radio... radios) {
return radioGroup(label, null, null, radios);
}
/**
* Builds a {@link RadioGroup} with auto-generated name property.
*
* @param label
* The field label.
* @param orientation
* The radios orientation.
* @param radios
* The {@link Radio} fields that belong to the group.
* @return The field.
*/
public static RadioGroup radioGroup(String label, Orientation orientation, Radio... radios) {
return radioGroup(label, null, orientation, radios);
}
/**
* Builds a {@link Radio}.
*
* @param label
* The field label.
* @param name
* The radios group name property. If {@code null}, default auto-generated name is set.
* @param orientation
* The radios orientation. If {@code null}, default horizontal orientation is set.
* @param radios
* The {@link Radio} fields that belong to the group.
* @return The field.
*/
public static RadioGroup radioGroup(String label, String name, Orientation orientation, Radio... radios) {
final RadioGroup field = new RadioGroup();
if (ClientUtils.isNotBlank(label)) {
field.setFieldLabel(label);
}
field.setName(ClientUtils.isNotBlank(name) ? name : Math.random() + "_" + new Date().getTime());
if (orientation != null) {
field.setOrientation(orientation);
}
if (ClientUtils.isNotEmpty(radios)) {
for (final Radio radio : radios) {
if (radio == null) {
continue;
}
field.add(radio);
}
}
return field;
}
// --
// -- CheckBox / CheckBoxGroup
// --
/**
* Builds a {@link CheckBox}.
*
* @param boxLabel
* The field <b>checkbox</b> label. None if {@code null}, but <em>empty</em> will generate one.
* @param stylenames
* (optional) Style name(s) added to the field. Blank values are ignored.
* @return The field.
*/
public static CheckBox checkbox(String boxLabel, String... stylenames) {
return checkbox(boxLabel, null, null, stylenames);
}
/**
* Builds a {@link CheckBox}.
*
* @param boxLabel
* The field <b>checkbox</b> label. None if {@code null}, but <em>empty</em> will generate one.
* @param value
* The field value ({@code null} means {@code false}).
* @param stylenames
* (optional) Style name(s) added to the field. Blank values are ignored.
* @return The field.
*/
public static CheckBox checkbox(String boxLabel, Boolean value, String... stylenames) {
return checkbox(boxLabel, null, value, stylenames);
}
/**
* Builds a {@link CheckBox}.
*
* @param boxLabel
* The field <b>checkbox</b> label. None if {@code null}, but <em>empty</em> will generate one.
* @param name
* The field name property (recommended for {@link CheckBoxGroup} fields).
* @param value
* The field value ({@code null} means {@code false}).
* @param stylenames
* (optional) Style name(s) added to the field. Blank values are ignored.
* @return The field.
*/
public static CheckBox checkbox(String boxLabel, String name, Boolean value, String... stylenames) {
return checkbox(boxLabel, name, null, value, stylenames);
}
/**
* Builds a {@link CheckBox}.
*
* @param boxLabel
* The field <b>checkbox</b> label. None if {@code null}, but <em>empty</em> will generate one.
* @param name
* The field name property (recommended for {@link CheckBoxGroup} fields).
* @param fieldLabel
* The field label.
* @param value
* The field value ({@code null} means {@code false}).
* @param stylenames
* (optional) Style name(s) added to the field. Blank values are ignored.
* @return The field.
*/
public static CheckBox checkbox(String boxLabel, String name, String fieldLabel, Boolean value, String... stylenames) {
final CheckBox field = new CheckBox();
// Should not process a 'null/blank' control to let the user set an empty boxLabel.
field.setBoxLabel(boxLabel);
if (ClientUtils.isNotBlank(name)) {
field.setName(name);
}
if (ClientUtils.isNotBlank(fieldLabel)) {
field.setFieldLabel(fieldLabel);
}
field.setValue(value);
return addStyles(field, stylenames);
}
/**
* Builds a {@link CheckBoxGroup} with auto-generated name property and default horizontal orientation.
*
* @param label
* The field label.
* @param checkBoxes
* The {@link CheckBox} fields that belong to the group.
* @return The field.
*/
public static CheckBoxGroup checkBoxGroup(String label, CheckBox... checkBoxes) {
return checkBoxGroup(label, null, null, checkBoxes);
}
/**
* Builds a {@link CheckBoxGroup} with auto-generated name property.
*
* @param label
* The field label.
* @param orientation
* The radios orientation.
* @param checkBoxes
* The {@link CheckBox} fields that belong to the group.
* @return The field.
*/
public static CheckBoxGroup checkBoxGroup(String label, Orientation orientation, CheckBox... checkBoxes) {
return checkBoxGroup(label, null, orientation, checkBoxes);
}
/**
* Builds a {@link CheckBoxGroup}.
*
* @param label
* The field label.
* @param name
* The checkboxes group name property. If {@code null}, default auto-generated name is set.
* @param orientation
* The checkboxes orientation. If {@code null}, default horizontal orientation is set.
* @param checkBoxes
* The {@link CheckBox} fields that belong to the group.
* @return The field.
*/
public static CheckBoxGroup checkBoxGroup(String label, String name, Orientation orientation, CheckBox... checkBoxes) {
final CheckBoxGroup field = new CheckBoxGroup();
if (ClientUtils.isNotBlank(label)) {
field.setFieldLabel(label);
}
field.setName(ClientUtils.isNotBlank(name) ? name : Math.random() + "_" + new Date().getTime());
if (orientation != null) {
field.setOrientation(orientation);
}
if (ClientUtils.isNotEmpty(checkBoxes)) {
for (final CheckBox checkBox : checkBoxes) {
if (checkBoxes == null) {
continue;
}
field.add(checkBox);
}
}
return field;
}
// --
// -- FileUpload
// --
/**
* Builds a {@link FileUploadField}.
*
* @param label
* The field label.
* @return The field.
*/
public static FileUploadField upload(String label) {
return upload(label, null);
}
/**
* Builds a {@link FileUploadField}.
*
* @param label
* The field label.
* @param name
* The field name property.
* @return The field.
*/
public static FileUploadField upload(String label, String name) {
final FileUploadField field = new FileUploadField();
if (ClientUtils.isNotBlank(label)) {
field.setFieldLabel(label);
}
if (ClientUtils.isNotBlank(name)) {
field.setName(name);
}
return field;
}
// --
// -- DateField
// --
/**
* Builds a {@link DateField}.
*
* @param label
* The field label.
* @param mandatory
* <code>true</code> if the field doesn't allow blanks, <code>false</code> otherwise.
* @param stylenames
* (optional) Style name(s) added to the field. Blank values are ignored.
* @return The field.
*/
public static DateField date(String label, boolean mandatory, String... stylenames) {
return date(label, mandatory, null, null, stylenames);
}
/**
* Builds a {@link DateField}.
*
* @param label
* The field label.
* @param mandatory
* <code>true</code> if the field doesn't allow blanks, <code>false</code> otherwise.
* @param minValue
* The min value date.
* @param maxValue
* The max value date.
* @param stylenames
* (optional) Style name(s) added to the field. Blank values are ignored.
* @return The field.
*/
public static DateField date(String label, boolean mandatory, Date minValue, Date maxValue, String... stylenames) {
final DateField field = new DateField();
// Label.
if (ClientUtils.isNotBlank(label)) {
field.setFieldLabel(label);
}
// Constraints.
field.setAllowBlank(!mandatory);
if (minValue != null) {
field.setMinValue(minValue);
}
if (maxValue != null) {
field.setMaxValue(maxValue);
}
return addStyles(field, stylenames);
}
// --
// -- TimeField
// --
/**
* Builds a {@link TimeField}.
*
* @param label
* The field label.
* @param mandatory
* <code>true</code> if the field doesn't allow blanks, <code>false</code> otherwise.
* @param stylenames
* (optional) Style name(s) added to the field. Blank values are ignored.
* @return The field.
*/
public static TimeField time(String label, boolean mandatory, String... stylenames) {
return time(label, mandatory, null, null, stylenames);
}
/**
* Builds a {@link TimeField}.
*
* @param label
* The field label.
* @param mandatory
* <code>true</code> if the field doesn't allow blanks, <code>false</code> otherwise.
* @param minValue
* The min value date.
* @param maxValue
* The max value date.
* @param stylenames
* (optional) Style name(s) added to the field. Blank values are ignored.
* @return The field.
*/
public static TimeField time(String label, boolean mandatory, Date minValue, Date maxValue, String... stylenames) {
final TimeField field = new TimeField();
// Label.
if (ClientUtils.isNotBlank(label)) {
field.setFieldLabel(label);
}
// Constraints.
field.setAllowBlank(!mandatory);
if (minValue != null) {
field.setMinValue(minValue);
}
if (maxValue != null) {
field.setMaxValue(maxValue);
}
// Necessary to avoid NPE in 'clear()' method.
field.setStore(new ListStore<Time>());
field.setTriggerAction(TriggerAction.ALL);
return addStyles(field, stylenames);
}
// --
// -- AdapterField
// --
/**
* Wraps the given {@code widget} with a ScollPanel and builds an
* {@link AdapterField} for it.
*
* @param label
* The field label. If {@code blank}, label separator is automatically disabled.
* @param widget
* The widget wrapped into the scroll panel and into the adapter field.
* @param width
* Width of the given widget.
* @param height
* Height of the scroll panel.
* @return The field.
*/
public static AdapterField adapterWithScrollbars(final String label, final IsWidget widget, final int width, final int height) {
final ScrollPanel scrollPanel = new ScrollPanel();
scrollPanel.setWidget(Widget.asWidgetOrNull(widget));
scrollPanel.addAttachHandler(new AttachEvent.Handler() {
@Override
public void onAttachOrDetach(AttachEvent event) {
scrollPanel.setWidth(width + "px");
}
});
scrollPanel.setHeight(height + "px");
return adapter(label, scrollPanel);
}
/**
* Builds an {@link AdapterField} for the given {@code widget}.
*
* @param label
* The field label. If {@code blank}, label separator is automatically disabled.
* @param widget
* The widget wrapped into the adapter field.
* @return The field.
*/
public static AdapterField adapter(final String label, final IsWidget widget) {
return adapter(label, widget, null);
}
/**
* Builds an {@link AdapterField} for the given {@code widget}.
*
* @param label
* The field label. If {@code blank}, label separator is automatically disabled.
* @param widget
* The widget wrapped into the adapter field.
* @param resizeWidget
* {@code true} to resize the widget.
* @return The field.
*/
public static AdapterField adapter(final String label, final IsWidget widget, final Boolean resizeWidget) {
final AdapterField field = new AdapterField(Widget.asWidgetOrNull(widget));
// Label.
if (ClientUtils.isNotBlank(label)) {
field.setFieldLabel(label);
} else {
field.setLabelSeparator("");
}
// Resize widget?
if (resizeWidget != null) {
field.setResizeWidget(resizeWidget.booleanValue());
}
return field;
}
// --
// -- HiddenField
// --
/**
* Builds a {@link HiddenField}.
*
* @param <D>
* The hidden field value type.
* @param name
* The field name property.
* @return The field.
*/
public static <D> HiddenField<D> hidden(final String name) {
final HiddenField<D> field = new HiddenField<D>();
// Name.
if (ClientUtils.isNotBlank(name)) {
field.setName(name);
}
return field;
}
// --
// -- Button
// --
/**
* Creates a new button.
*
* @return A new button.
*/
public static Button button() {
return new Button();
}
/**
* Creates a new button with the given HTML.
*
* @param html
* the button text as HTML.
*
* @return A new button with the given label.
*/
public static Button button(final String html) {
return new Button(html);
}
/**
* Creates a new button with the given HTML and icon.
*
* @param html
* the button text as HTML.
* @param icon
* the icon.
*
* @return A new button with the given label and the given icon.
*/
public static Button button(final String html, final AbstractImagePrototype icon) {
return new Button(html, icon);
}
/**
* Creates a new button with the given HTML, icon and specified selection listener.
*
* @param html
* the button text as HTML.
* @param icon
* the icon.
* @param listener
* the selection listener.
*
* @return A new button with the given listener.
*/
public static Button button(final String html, final AbstractImagePrototype icon, final SelectionListener<ButtonEvent> listener) {
return new Button(html, icon, listener);
}
/**
* Creates a new button with the given HTML and specified selection listener.
*
* @param html
* the button's text as HTML.
* @param listener
* the selection listener.
*
* @return A new button with the given listener.
*/
public static Button button(final String html, final SelectionListener<ButtonEvent> listener) {
return new Button(html, listener);
}
/**
* Creates a new button with the given HTML and icon.
*
* @param html
* the button text as HTML.
* @param icon
* the icon.
*
* @return A new button with the given label and the given icon.
*/
public static SplitButton splitButton(final String html, final AbstractImagePrototype icon) {
return new SplitButton(html, icon);
}
/**
* Creates a new save split button and its menu composed of a save item and a discard changes item.
*
* @return A new save split button.
*/
public static SplitButton saveSplitButton() {
final SplitButton saveButton = Forms.splitButton(I18N.CONSTANTS.save(), IconImageBundle.ICONS.save());
// Menu attached to the save button.
final Menu menu = new Menu();
menu.add(new MenuItem(I18N.CONSTANTS.save(), IconImageBundle.ICONS.save()));
menu.add(new MenuItem(I18N.CONSTANTS.discardChanges(), IconImageBundle.ICONS.cancel()));
saveButton.setMenu(menu);
return saveButton;
}
// --
// -- Utility methods.
// --
/**
* Adds the given {@code stylenames} to the given {@code ui}.
*
* @param ui
* The UI object. Does nothing if {@code null}.
* @param stylenames
* The style name(s). Does nothing if {@code null}.
* @return The given {@code ui} with added style(s).
*/
private static <U extends UIObject> U addStyles(final U ui, String... stylenames) {
if (ui == null || ClientUtils.isEmpty(stylenames)) {
return ui;
}
for (final String stylename : stylenames) {
if (ClientUtils.isBlank(stylename)) {
continue;
}
ui.addStyleName(stylename);
}
return ui;
}
/**
* Private constructor.
*/
private Forms() {
// Factory pattern.
}
}