/* * Copyright 2009-2011 the original author or authors. * * Licensed 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.jdal.vaadin.ui; import java.text.DateFormat; import java.text.SimpleDateFormat; import java.util.Collection; import java.util.Collections; import java.util.List; import java.util.Locale; import org.apache.commons.lang.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.jdal.beans.StaticMessageSource; import org.jdal.cmd.Command; import org.jdal.util.comparator.PropertyComparator; import org.jdal.vaadin.ui.table.ButtonListener; import org.springframework.beans.BeanWrapper; import org.springframework.beans.PropertyAccessorFactory; import org.springframework.context.i18n.LocaleContextHolder; import com.vaadin.data.Property.ValueChangeEvent; import com.vaadin.data.Property.ValueChangeListener; import com.vaadin.server.ClassResource; import com.vaadin.server.ExternalResource; import com.vaadin.server.Resource; import com.vaadin.server.Sizeable.Unit; import com.vaadin.server.ThemeResource; import com.vaadin.shared.ui.label.ContentMode; import com.vaadin.ui.AbstractSelect; import com.vaadin.ui.AbstractSelect.ItemCaptionMode; import com.vaadin.ui.Alignment; import com.vaadin.ui.Button; import com.vaadin.ui.Button.ClickEvent; import com.vaadin.ui.Button.ClickListener; import com.vaadin.ui.ComboBox; import com.vaadin.ui.Component; import com.vaadin.ui.DateField; import com.vaadin.ui.Form; import com.vaadin.ui.HorizontalLayout; import com.vaadin.ui.Label; import com.vaadin.ui.NativeButton; import com.vaadin.ui.PasswordField; import com.vaadin.ui.TextArea; import com.vaadin.ui.TextField; import com.vaadin.ui.TwinColSelect; import com.vaadin.ui.UI; import com.vaadin.ui.VerticalLayout; import com.vaadin.ui.Window; import com.vaadin.ui.themes.Reindeer; /** * Form Utility Library * * @author Jose Luis Martin */ public abstract class FormUtils { public static int OK = 0; public static int CANCEL = 1; public static final String THEME_PREFIX = "theme:"; public static final String CLASSPATH_PREFIX = "classpath:"; public static final String URL_PREFIX = "url:"; private static final Log log = LogFactory.getLog(FormUtils.class); /** * Add a default commit/discard buttons to a form * @param f the Form */ public static void addOKCancelButtons(Form f) { Button ok = newOKButton(f); Button cancel = newCancelButton(f); HorizontalLayout hl = new HorizontalLayout(); hl.setSpacing(true); hl.addComponent(ok); hl.addComponent(cancel); HorizontalLayout footer = new HorizontalLayout(); footer.setWidth("100%"); footer.addComponent(hl); footer.setComponentAlignment(hl, Alignment.TOP_CENTER); f.setFooter(footer); } /** * Creates a new cancel button * @param f form holding the button * @return new cancel button */ private static Button newCancelButton(final Form f) { Button cancel = new Button(StaticMessageSource.getMessage("cancel")); cancel.addClickListener(new ClickListener() { public void buttonClick(ClickEvent event) { f.discard(); } }); return cancel; } /** * Creates a new OK Button * @param f form holding the button * @return new OK Button */ private static Button newOKButton(final Form f) { Button ok = new Button(StaticMessageSource.getMessage("ok")); ok.addClickListener(new ClickListener() { public void buttonClick(ClickEvent event) { f.commit(); } }); return ok; } /** * Closes a sub Window * @param window Window to close */ public static void closeWindow(Window window) { window.getUI().removeWindow(window); } /** * Build a new Button from Button Listener * @param buttonListener * @return a new Button */ public static Button newButton(ButtonListener buttonListener) { Button b = new Button(buttonListener.getCaption(), buttonListener); b.setIcon(buttonListener.getIcon()); b.setDescription(buttonListener.getDescription()); return b; } /** * Build a new Button from Button Listener * @param buttonListener * @param native true for native buttons. * @return a new Button */ public static Button newButton(ButtonListener buttonListener, boolean isNative) { if (isNative) return newNativeButton(buttonListener); return newButton(buttonListener); } /** * Show a YES/NO confirm dialog * @param window Window to attach the dialog * @param msg the msg */ public static void showConfirmDialog(UI ui, final Command command, String msg) { final Window dlg = new Window("Please Confirm"); VerticalLayout vl = new VerticalLayout(); vl.setSizeFull(); vl.setSpacing(true); vl.setMargin(true); Label label = new Label(msg, Label.CONTENT_XHTML); vl.addComponent(label); HorizontalLayout hl = new HorizontalLayout(); hl.setSpacing(true); Button ok = new Button(StaticMessageSource.getMessage("yes")); ok.addClickListener(new ClickListener() { public void buttonClick(ClickEvent event) { command.execute(null); closeWindow(dlg); } }); Button cancel = new Button(StaticMessageSource.getMessage("no")); cancel.addClickListener(new ClickListener() { public void buttonClick(ClickEvent event) { closeWindow(dlg); } }); hl.setSpacing(true); hl.addComponent(ok); hl.addComponent(cancel); hl.setSizeFull(); vl.addComponent(hl); vl.setComponentAlignment(hl, Alignment.TOP_CENTER); dlg.setContent(vl); dlg.setModal(true); vl.setSizeUndefined(); ui.addWindow(dlg); } /** * Add a List of objects to a combo * @param combo combo to add items * @param items items to add */ public static void addItemList(AbstractSelect combo, List<?> items) { combo.setItemCaptionMode(ItemCaptionMode.ID); for (Object item : items) combo.addItem(item); } public static ComboBox newComboBox(List<?> elements, String sortProperty, String caption) { Collections.sort(elements, new PropertyComparator(sortProperty)); ComboBox combo = new ComboBox(caption); addItemList(combo, elements); return combo; } /** * Create a new {@link TextField} * @return new TextField with null representation set to empty string */ public static TextField newTextField() { TextField tf = new TextField(); tf.setNullRepresentation(""); return tf; } /** * Create a new {@link PasswordField} * @return new PasswordField with null representation set to emptry string. */ public static PasswordField newPasswordField() { PasswordField pf = new PasswordField(); pf.setNullRepresentation(""); return pf; } /** * Create a new {@link NativeButton} from an {@link ButtonListener} * @param action button listener * @return a new native button. */ public static NativeButton newNativeButton(ButtonListener action) { NativeButton b = new NativeButton(action.getCaption(), action); b.setIcon(action.getIcon()); b.setDescription(action.getDescription()); return b; } /** * Create a new DateField with format for current locale and {@link DateFormat#SHORT} style * @return a new DateField */ public static DateField newDateField() { return newDateField(DateFormat.SHORT); } /** * Create a new DateField with format for current locale and given style. * @param style DateFormat style * @return a new DateField */ public static DateField newDateField(int style) { DateField df = new DateField(); Locale locale = LocaleContextHolder.getLocale(); df.setLocale(locale); DateFormat dateFormat = DateFormat.getDateInstance(style); if (dateFormat instanceof SimpleDateFormat) { SimpleDateFormat sdf = (SimpleDateFormat) dateFormat; df.setDateFormat(sdf.toPattern()); } return df; } public static void showDialog(Component component, String caption, String width, String height) { Dialog dlg = new Dialog(component); dlg.setWidth(width); dlg.setHeight(height); dlg.center(); dlg.setCaption(caption); dlg.show(); } public static void showDialog(Component component, String caption) { showDialog(component, caption, "80%", "80%"); } /** * Fill combo with a list of objects removing all items. * * @param data list to fill with. * @param clear true if clear all items before adding new ones. */ public static void fillCombo(ComboBox combo, List<?> data) { fillCombo(combo, data, true); } /** * Fill combo with a list of objeces. * @param data list to fill with. * @param clear true if clear all items before adding new ones. */ public static void fillCombo(ComboBox combo, List<?> data, boolean clear) { Object selected = combo.getValue(); if (clear) { combo.removeAllItems(); } for (Object o : data) { combo.addItem(o); } if (data.contains(selected)) combo.setValue(selected); } /** * Gets resource from url using the following prefix * <ul> * <li> classpath: for searching the classpath.</li> * <li> theme: for searching in current theme </li> * <li> url: to use a url </li> * </ul> * @param url resource url * @return the resource. */ public static Resource getResource(String url) { Resource resource; if (url.startsWith(CLASSPATH_PREFIX)) resource = new ClassResource(StringUtils.substringAfter(url, CLASSPATH_PREFIX)); else if (url.startsWith(THEME_PREFIX)) resource = new ThemeResource(StringUtils.substringAfter(url, THEME_PREFIX)); else if (url.startsWith(URL_PREFIX)) resource = new ExternalResource(StringUtils.substringAfter(url, URL_PREFIX)); else if (url.contains(":")) resource = new ExternalResource(url); else resource = new ThemeResource(url); return resource; } /** * Create a new TextArea with current locale from {@link LocaleContextHolder} * @return a new TextArea */ public static TextArea newTextArea() { TextArea area = new TextArea(); area.setNullRepresentation(""); area.setLocale(LocaleContextHolder.getLocale()); return area; } /** * Add a link on primary and dependent ComboBoxes by property name. * When selection changes on primary use propertyName to get a Collection and fill dependent ComboBox with it * @param primary ComboBox when selection changes * @param dependent ComboBox that are filled with collection * @param propertyName the property name for get the collection from primary selected item */ public static void link(final ComboBox primary, final ComboBox dependent, final String propertyName) { link(primary, dependent, propertyName, false); } /** * Add a link on primary and dependent ComboBoxes by property name. * When selection changes on primary use propertyName to get a Collection and fill dependent ComboBox with it * @param primary ComboBox when selection changes * @param dependent ComboBox that are filled with collection * @param propertyName the property name for get the collection from primary selected item * @param addNull if true, add a null as first combobox item */ @SuppressWarnings("rawtypes") public static void link(final ComboBox primary, final ComboBox dependent, final String propertyName, final boolean addNull) { primary.addValueChangeListener(new ValueChangeListener() { public void valueChange(ValueChangeEvent event) { Object selected = event.getProperty().getValue(); if (selected != null) { BeanWrapper wrapper = PropertyAccessorFactory.forBeanPropertyAccess(selected); if (wrapper.isReadableProperty(propertyName)) { Collection items = (Collection) wrapper.getPropertyValue(propertyName); dependent.removeAllItems(); if (addNull) dependent.addItem(null); for (Object item : items) dependent.addItem(item); } else { log.error("Can't write on propety '" + propertyName + "' of class: '" + selected.getClass() + "'"); } } } }); } /** * Create a titled separator * @param title title * @return a {@link HorizontalLayout} with title and rule. */ public static Component createTitledSeparator(String title) { Label titleLabel = new Label(title); titleLabel.setStyleName(Reindeer.LABEL_H2); Label rule = new Label("<hr />", ContentMode.HTML); titleLabel.setSizeUndefined(); HorizontalLayout hl = new HorizontalLayout(); hl.addComponent(titleLabel); Box.addHorizontalStruct(hl, 20); hl.addComponent(rule); hl.setComponentAlignment(rule, Alignment.BOTTOM_CENTER); hl.setExpandRatio(rule, 1); hl.setWidth(100, Unit.PERCENTAGE); return hl; } /** * Crate a {@link TwinColSelect} */ public static TwinColSelect newTwinColSelect() { TwinColSelect select = new TwinColSelect(); select.setLocale(LocaleContextHolder.getLocale()); return select; } }