/* * 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 de.unioninvestment.eai.portal.portlet.crud.mvp.views; import java.util.Date; import java.util.Locale; import java.util.Set; import com.vaadin.event.Action; import com.vaadin.event.Action.Handler; import com.vaadin.event.ShortcutAction; import com.vaadin.event.ShortcutAction.KeyCode; import com.vaadin.shared.ui.MarginInfo; import com.vaadin.ui.AbstractComponent; 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.CheckBox; import com.vaadin.ui.ComboBox; import com.vaadin.ui.CssLayout; import com.vaadin.ui.Field; import com.vaadin.ui.FormLayout; import com.vaadin.ui.GridLayout; import com.vaadin.ui.HorizontalLayout; import com.vaadin.ui.Label; import com.vaadin.ui.Layout; import com.vaadin.ui.ListSelect; import com.vaadin.ui.Panel; import com.vaadin.ui.PopupDateField; import com.vaadin.ui.TextField; import com.vaadin.ui.UI; import com.vaadin.ui.VerticalLayout; import com.vaadin.ui.themes.LiferayTheme; import de.unioninvestment.eai.portal.portlet.crud.domain.form.SearchFormAction; import de.unioninvestment.eai.portal.portlet.crud.domain.model.CheckBoxFormField; import de.unioninvestment.eai.portal.portlet.crud.domain.model.DateFormField; import de.unioninvestment.eai.portal.portlet.crud.domain.model.FormAction; import de.unioninvestment.eai.portal.portlet.crud.domain.model.FormActions; import de.unioninvestment.eai.portal.portlet.crud.domain.model.FormField; import de.unioninvestment.eai.portal.portlet.crud.domain.model.FormFields; import de.unioninvestment.eai.portal.portlet.crud.domain.model.MultiOptionListFormField; import de.unioninvestment.eai.portal.portlet.crud.domain.model.OptionList; import de.unioninvestment.eai.portal.portlet.crud.domain.model.OptionListFormField; import de.unioninvestment.eai.portal.portlet.crud.mvp.views.ui.OptionListContainer; import de.unioninvestment.eai.portal.portlet.crud.scripting.domain.FormSelectionContext; import de.unioninvestment.eai.portal.support.vaadin.date.DateUtils; import de.unioninvestment.eai.portal.support.vaadin.mvp.View; import de.unioninvestment.eai.portal.support.vaadin.support.ConvertablePropertyWrapper; import de.unioninvestment.eai.portal.support.vaadin.validation.FieldValidator; /** * {@link View} für Formularansicht. Bei einspaltiger Ansicht werden die Felder * untereinander, und links davon als Label jeweils die Titel angezeigt. Bei * mehrspaltiger Ansicht werden die Label über den Eingabefeldern angezeigt. * * Unter den Eingabefeldern werden Aktions-Buttons horizontal angeordnet * dargestellt. * * @author carsten.mjartan */ public class DefaultFormView extends Panel implements FormView, Handler { private static final long serialVersionUID = 1L; private static final Action ACTION_ENTER = new ShortcutAction("Enter", KeyCode.ENTER, null); private static final Action[] FORM_ACTIONS = { ACTION_ENTER }; private Presenter presenter; private FormAction searchAction; private VerticalLayout rootLayout; private Layout fieldLayout; @Override public void initialize(Presenter presenter, de.unioninvestment.eai.portal.portlet.crud.domain.model.Form model) { // @since 1.45 if (model.getWidth() != null) { setWidth(model.getWidth()); } // @since 1.45 if (model.getHeight() != null) { setHeight(model.getHeight()); } this.presenter = presenter; int columns = model.getColumns(); FormFields fields = model.getFields(); FormActions actions = model.getActions(); rootLayout = new VerticalLayout(); setStyleName(LiferayTheme.PANEL_LIGHT); addStyleName("c2g-form"); setContent(rootLayout); addActionHandler(this); if (columns > 1) { fieldLayout = layoutAsGrid(columns, fields.count()); } else { fieldLayout = layoutAsForm(); } populateFields(fields, columns); rootLayout.addComponent(fieldLayout); createFooterAndPopulateActions(actions); } private Layout layoutAsForm() { return new FormLayout(); } private GridLayout layoutAsGrid(int columns, int fieldCount) { int rows = calculateRowCount(columns, fieldCount); GridLayout grid = new GridLayout(columns, rows); grid.setMargin(new MarginInfo(true, false, true, false)); grid.setSpacing(true); grid.setWidth("100%"); return grid; } private void populateFields(FormFields fields, int columns) { for (FormField field : fields) { Field<?> vaadinField; if (field instanceof MultiOptionListFormField) { vaadinField = createMultiSelect((MultiOptionListFormField) field); } else if (field instanceof OptionListFormField) { vaadinField = createSelect((OptionListFormField) field); } else if (field instanceof CheckBoxFormField) { vaadinField = createCheckBox(field, columns); } else if (field instanceof DateFormField) { vaadinField = createDateFormField(field); } else { vaadinField = createTextField(field); } applyValidators(field, vaadinField); if (!(field instanceof CheckBoxFormField)) { addFieldToLayout(field, vaadinField); } } } private Field<Date> createDateFormField(FormField field) { DateFormField dff = (DateFormField) field; PopupDateField datetime = new PopupDateField(field.getTitle()); datetime.setInputPrompt(field.getInputPrompt()); datetime.setDateFormat(dff.getDateFormat()); datetime.setLocale(Locale.GERMAN); datetime.setResolution(DateUtils.getVaadinResolution(dff .getResolution())); ConvertablePropertyWrapper<Date, String> wrapper = new ConvertablePropertyWrapper<Date, String>( dff.getProperty(), dff.getConverter(), UI.getCurrent() .getLocale()); datetime.setPropertyDataSource(wrapper); datetime.setImmediate(true); datetime.addStyleName(field.getName()); return datetime; } private Field<String> createTextField(FormField field) { TextField textField = new TextField(field.getTitle(), field.getProperty()); // applyValidators(field, textField); textField.setNullSettingAllowed(true); textField.setNullRepresentation(""); textField.setImmediate(true); textField.addStyleName(field.getName()); applyInputPrompt(field, textField); return textField; } private void addFieldToLayout(FormField field, Field<?> vaadinField) { fieldLayout.addComponent(vaadinField); if (fieldLayout instanceof GridLayout) { vaadinField.setWidth("100%"); if (field.getTitle().length() > 15) { if (vaadinField instanceof AbstractComponent) { ((AbstractComponent) vaadinField).setDescription(field .getTitle()); } } ((GridLayout) fieldLayout).setComponentAlignment(vaadinField, Alignment.BOTTOM_LEFT); } } private void applyValidators(FormField field, Field<?> textField) { if (field.getValidators() != null) { for (FieldValidator validator : field.getValidators()) { validator.apply(textField); } } } private Field<?> createSelect(OptionListFormField field) { AbstractSelect select; if (field.getVisibleRows() <= 1) { select = new ComboBox(field.getTitle()); } else { select = new ListSelect(field.getTitle()); ((ListSelect) select).setRows(field.getVisibleRows()); } fillOptions(field.getOptionList(), select, new FormSelectionContext( field)); // addOptionListChangeListener(field, select, new FormSelectionContext( // field)); select.setPropertyDataSource(field.getProperty()); select.setInvalidAllowed(false); select.setImmediate(true); select.setMultiSelect(false); select.addStyleName(field.getName()); return select; } private Field<?> createMultiSelect(MultiOptionListFormField field) { ListSelect select = new ListSelect(field.getTitle()); fillOptions(field.getOptionList(), select, new FormSelectionContext( field)); // addOptionListChangeListener(field, select, new FormSelectionContext( // field)); select.setMultiSelect(true); select.setPropertyDataSource(field.getListProperty()); select.setInvalidAllowed(false); select.setImmediate(true); select.setRows(field.getVisibleRows()); select.addStyleName(field.getName()); return select; } private void fillOptions(OptionList optionList, AbstractSelect select, FormSelectionContext ctx) { Object currentValue = select.getValue(); select.setContainerDataSource(new OptionListContainer(optionList, ctx)); select.setItemCaptionMode(ItemCaptionMode.PROPERTY); select.setItemCaptionPropertyId("title"); reapplyCurrentValue(select, currentValue); } private void reapplyCurrentValue(AbstractSelect select, Object currentValue) { if (currentValue != null) { if (select.isMultiSelect()) { for (Object element : (Set<?>) currentValue) { if (select.containsId(element)) { select.select(element); } } } else { if (select.containsId(currentValue)) { select.setValue(currentValue); } } } } private Field<Boolean> createCheckBox(FormField field, int columns) { CheckBoxFormField checkBoxFormField = (CheckBoxFormField) field; Layout checkboxLayout = null; if (columns == 1) { checkboxLayout = new HorizontalLayout(); checkboxLayout.setCaption(field.getTitle()); } else { checkboxLayout = new VerticalLayout(); Label checkBoxLabel = new Label(field.getTitle()); checkboxLayout.addComponent(checkBoxLabel); } CheckBox checkBoxField = new CheckBox(); checkboxLayout.addComponent(checkBoxField); checkBoxField.setConverter(checkBoxFormField.getConverter()); checkBoxField.setPropertyDataSource(checkBoxFormField.getProperty()); checkBoxField.setImmediate(true); checkBoxField.addStyleName(field.getName()); // addField(field.getName(), checkBoxField); fieldLayout.addComponent(checkboxLayout); return checkBoxField; } private void applyInputPrompt(FormField field, TextField textField) { String inputPrompt = field.getInputPrompt(); if (inputPrompt != null) { textField.setInputPrompt(inputPrompt); } } @SuppressWarnings("serial") private void createFooterAndPopulateActions(FormActions actions) { CssLayout buttons = new CssLayout(); buttons.setStyleName("actions"); boolean allHidden = true; for (final FormAction action : actions) { final Button button = new Button(action.getTitle()); button.setDisableOnClick(true); button.addClickListener(new ClickListener() { @Override public void buttonClick(ClickEvent event) { try { presenter.executeAction(action); } finally { button.setEnabled(true); } } }); if (action.getActionHandler() instanceof SearchFormAction) { if (searchAction == null) { searchAction = action; // button.setClickShortcut(KeyCode.ENTER); } } if (action.isHidden()) { button.setVisible(false); } else { allHidden = false; } buttons.addComponent(button); } if (!allHidden) { rootLayout.addComponent(buttons); } } /** * Berechnet die Anzahl der Zeilen. * * @param columns * Spalten * @param fieldCount * Anzahl Felder * @return Anzahl Zeilen */ static int calculateRowCount(int columns, int fieldCount) { return ((fieldCount - 1) / columns) + 1; } @Override public FormAction getSearchAction() { return searchAction; } @Override public Action[] getActions(Object target, Object sender) { if (searchAction != null && sender == this) { return FORM_ACTIONS; } return null; } @Override public void handleAction(Action action, Object sender, Object target) { if (action == ACTION_ENTER) { presenter.executeAction(searchAction); } } }