package org.activityinfo.ui.client.component.formdesigner.properties; /* * #%L * ActivityInfo Server * %% * Copyright (C) 2009 - 2013 UNICEF * %% * 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 com.google.common.base.Strings; import com.google.common.collect.Lists; import com.google.gwt.core.client.GWT; import com.google.gwt.event.dom.client.ClickEvent; import com.google.gwt.event.dom.client.ClickHandler; import com.google.gwt.event.dom.client.KeyUpEvent; import com.google.gwt.event.dom.client.KeyUpHandler; import com.google.gwt.event.logical.shared.ValueChangeEvent; import com.google.gwt.event.logical.shared.ValueChangeHandler; import com.google.gwt.event.shared.HandlerRegistration; import com.google.gwt.user.client.rpc.AsyncCallback; import org.activityinfo.core.client.ResourceLocator; import org.activityinfo.i18n.shared.I18N; import org.activityinfo.model.form.FormClass; import org.activityinfo.model.form.FormField; import org.activityinfo.model.resource.Record; import org.activityinfo.model.resource.Resources; import org.activityinfo.model.type.FieldValue; import org.activityinfo.model.type.ParametrizedFieldType; import org.activityinfo.model.type.ParametrizedFieldTypeClass; import org.activityinfo.model.type.expr.CalculatedFieldType; import org.activityinfo.model.type.expr.ExprValue; import org.activityinfo.ui.client.component.form.HorizontalFieldContainer; import org.activityinfo.ui.client.component.form.SimpleFormPanel; import org.activityinfo.ui.client.component.form.field.FieldWidgetMode; import org.activityinfo.ui.client.component.form.field.FormFieldWidgetFactory; import org.activityinfo.ui.client.component.formdesigner.FormDesigner; import org.activityinfo.ui.client.component.formdesigner.container.FieldWidgetContainer; import org.activityinfo.ui.client.component.formdesigner.container.WidgetContainer; import org.activityinfo.ui.client.component.formdesigner.event.HeaderSelectionEvent; import org.activityinfo.ui.client.component.formdesigner.event.WidgetContainerSelectionEvent; import org.activityinfo.ui.client.component.formdesigner.header.HeaderPresenter; import org.activityinfo.ui.client.component.formdesigner.skip.SkipDialog; import java.util.List; /** * @author yuriyz on 7/9/14. */ public class PropertiesPresenter { private final FormDesigner formDesigner; private final PropertiesPanel view; private SimpleFormPanel currentDesignWidget = null; private HandlerRegistration labelKeyUpHandler; private HandlerRegistration descriptionKeyUpHandler; private HandlerRegistration codeKeyUpHandler; private HandlerRegistration requiredValueChangeHandler; private HandlerRegistration readonlyValueChangeHandler; private HandlerRegistration visibleValueChangeHandler; private HandlerRegistration relevanceButtonClickHandler; private HandlerRegistration relevanceEnabledValueHandler; private HandlerRegistration relevanceEnabledIfValueHandler; public PropertiesPresenter(PropertiesPanel view, FormDesigner formDesigner) { this.view = view; this.formDesigner = formDesigner; formDesigner.getEventBus().addHandler(WidgetContainerSelectionEvent.TYPE, new WidgetContainerSelectionEvent.Handler() { @Override public void handle(WidgetContainerSelectionEvent event) { WidgetContainer widgetContainer = event.getSelectedItem(); if (widgetContainer instanceof FieldWidgetContainer) { show((FieldWidgetContainer) widgetContainer); } } }); formDesigner.getEventBus().addHandler(HeaderSelectionEvent.TYPE, new HeaderSelectionEvent.Handler() { @Override public void handle(HeaderSelectionEvent event) { show(event.getSelectedItem()); } }); reset(); } public PropertiesPanel getView() { return view; } private void reset() { if (currentDesignWidget != null) { view.getPanel().remove(currentDesignWidget); currentDesignWidget = null; } view.getRequiredGroup().setVisible(false); view.getReadOnlyGroup().setVisible(false); view.getVisibleGroup().setVisible(false); view.getRelevanceGroup().setVisible(false); view.getCodeGroup().setVisible(false); if (labelKeyUpHandler != null) { labelKeyUpHandler.removeHandler(); } if (descriptionKeyUpHandler != null) { descriptionKeyUpHandler.removeHandler(); } if (codeKeyUpHandler != null) { codeKeyUpHandler.removeHandler(); } if (requiredValueChangeHandler != null) { requiredValueChangeHandler.removeHandler(); } if (readonlyValueChangeHandler != null) { readonlyValueChangeHandler.removeHandler(); } if (relevanceButtonClickHandler != null) { relevanceButtonClickHandler.removeHandler(); } if (visibleValueChangeHandler != null) { visibleValueChangeHandler.removeHandler(); } if (relevanceEnabledValueHandler != null) { relevanceEnabledValueHandler.removeHandler(); } if (relevanceEnabledIfValueHandler != null) { relevanceEnabledIfValueHandler.removeHandler(); } } private void show(final FieldWidgetContainer fieldWidgetContainer) { reset(); final FormField formField = fieldWidgetContainer.getFormField(); view.setVisible(true); view.getRequiredGroup().setVisible(true); view.getReadOnlyGroup().setVisible(true); view.getVisibleGroup().setVisible(true); view.getRelevanceGroup().setVisible(true); view.getCodeGroup().setVisible(true); view.getLabel().setValue(Strings.nullToEmpty(formField.getLabel())); view.getDescription().setValue(Strings.nullToEmpty(formField.getDescription())); view.getRequired().setValue(formField.isRequired()); view.getVisible().setValue(formField.isVisible()); view.getCode().setValue(Strings.nullToEmpty(formField.getCode())); setRelevanceState(formField, true); validateCode(fieldWidgetContainer); validateLabel(); relevanceButtonClickHandler = view.getRelevanceButton().addClickHandler(new ClickHandler() { @Override public void onClick(ClickEvent event) { SkipDialog dialog = new SkipDialog(fieldWidgetContainer, PropertiesPresenter.this); dialog.show(); } }); labelKeyUpHandler = view.getLabel().addKeyUpHandler(new KeyUpHandler() { @Override public void onKeyUp(KeyUpEvent event) { if (validateLabel()) { formField.setLabel(view.getLabel().getValue()); fieldWidgetContainer.syncWithModel(); } } }); descriptionKeyUpHandler = view.getDescription().addKeyUpHandler(new KeyUpHandler() { @Override public void onKeyUp(KeyUpEvent event) { formField.setDescription(view.getDescription().getValue()); fieldWidgetContainer.syncWithModel(); } }); codeKeyUpHandler = view.getCode().addKeyUpHandler(new KeyUpHandler() { @Override public void onKeyUp(KeyUpEvent keyUpEvent) { if (validateCode(fieldWidgetContainer)) { formField.setCode(view.getCode().getValue()); fieldWidgetContainer.syncWithModel(); } } }); requiredValueChangeHandler = view.getRequired().addValueChangeHandler(new ValueChangeHandler<Boolean>() { @Override public void onValueChange(ValueChangeEvent<Boolean> event) { formField.setRequired(view.getRequired().getValue()); fieldWidgetContainer.syncWithModel(); } }); readonlyValueChangeHandler = view.getReadOnly().addValueChangeHandler(new ValueChangeHandler<Boolean>() { @Override public void onValueChange(ValueChangeEvent<Boolean> event) { formField.setReadOnly(view.getReadOnly().getValue()); fieldWidgetContainer.syncWithModel(); } }); visibleValueChangeHandler = view.getVisible().addValueChangeHandler(new ValueChangeHandler<Boolean>() { @Override public void onValueChange(ValueChangeEvent<Boolean> event) { formField.setVisible(view.getVisible().getValue()); if (!view.getVisible().getValue()) { // invisible formfield must not be required -> user is not able to set value for invisible field view.getRequired().setValue(false); formField.setRequired(false); } fieldWidgetContainer.syncWithModel(); } }); relevanceEnabledValueHandler = view.getRelevanceEnabled().addValueChangeHandler(new ValueChangeHandler<Boolean>() { @Override public void onValueChange(ValueChangeEvent<Boolean> booleanValueChangeEvent) { formField.setRelevanceConditionExpression(null); setRelevanceState(formField, false); } }); relevanceEnabledIfValueHandler = view.getRelevanceEnabledIf().addValueChangeHandler(new ValueChangeHandler<Boolean>() { @Override public void onValueChange(ValueChangeEvent<Boolean> booleanValueChangeEvent) { setRelevanceState(formField, false); } }); ResourceLocator locator = fieldWidgetContainer.getFormDesigner().getResourceLocator(); currentDesignWidget = new SimpleFormPanel(locator, new HorizontalFieldContainer.Factory(), new FormFieldWidgetFactory(locator, FieldWidgetMode.NORMAL), false) { @Override public void onFieldUpdated(FormField field, FieldValue newValue) { super.onFieldUpdated(field, newValue); ParametrizedFieldType parametrizedFieldType = (ParametrizedFieldType) formField.getType(); Record param = parametrizedFieldType.getParameters(); param.set(field.getId(), newValue); ParametrizedFieldTypeClass typeClass = (ParametrizedFieldTypeClass) parametrizedFieldType.getTypeClass(); if (formField.getType() instanceof CalculatedFieldType && newValue instanceof ExprValue) { // for calculated fields we updated expression directly because it is handled via ExprFieldType ExprValue exprValue = (ExprValue) newValue; ((CalculatedFieldType) formField.getType()).setExpression(exprValue.getExpression()); } else { formField.setType(typeClass.deserializeType(param)); } fieldWidgetContainer.syncWithModel(); formDesigner.getSavedGuard().setSaved(false); } }; if (formField.getType() instanceof ParametrizedFieldType) { ParametrizedFieldType parametrizedType = (ParametrizedFieldType) formField.getType(); currentDesignWidget.asWidget().setVisible(true); currentDesignWidget.setValidationFormClass(fieldWidgetContainer.getFormDesigner().getFormClass()); currentDesignWidget.show(Resources.createResource(parametrizedType.getParameters())).then(new AsyncCallback<Void>() { @Override public void onFailure(Throwable caught) { GWT.log("Exception thrown while showing properties form", caught); } @Override public void onSuccess(Void result) { } }); } else { currentDesignWidget.asWidget().setVisible(false); } view.getPanel().add(currentDesignWidget); } /** * Returns whether code is valid. * * @return whether code is valid */ private boolean validateCode(FieldWidgetContainer fieldWidgetContainer) { view.getCodeGroup().setShowValidationMessage(false); String code = view.getCode().getValue(); if (Strings.isNullOrEmpty(code)) { return true; } if (!FormField.isValidCode(code)) { view.getCodeGroup().showValidationMessage(I18N.CONSTANTS.invalidCodeMessage()); return false; } else { // check whether code is unique List<FormField> formFields = Lists.newArrayList(fieldWidgetContainer.getFormDesigner().getFormClass().getFields()); formFields.remove(fieldWidgetContainer.getFormField()); for (FormField formField : formFields) { if (code.equals(formField.getCode())) { view.getCodeGroup().showValidationMessage(I18N.CONSTANTS.duplicateCodeMessage()); return false; } } return true; } } /** * Returns whether code is valid. * * @return whether code is valid */ private boolean validateLabel() { view.getLabelGroup().setShowValidationMessage(false); if (Strings.isNullOrEmpty(view.getLabel().getValue())) { view.getLabelGroup().setShowValidationMessage(true); return false; } return true; } public void setRelevanceState(FormField formField, boolean setRadioButtonsState) { if (setRadioButtonsState) { if (formField.hasRelevanceConditionExpression()) { view.getRelevanceEnabledIf().setValue(true); } else { view.getRelevanceEnabled().setValue(true); } } view.getRelevanceButton().setEnabled(view.getRelevanceEnabledIf().getValue()); // view.getRelevanceState().setText(formField.hasRelevanceConditionExpression() ? I18N.CONSTANTS.defined() : I18N.CONSTANTS.no()); // view.getRelevanceExpression().setInnerText(formField.getRelevanceConditionExpression()); // if (formField.hasRelevanceConditionExpression()) { // view.getRelevanceExpression().removeClassName("hide"); // } else if (!view.getRelevanceExpression().getClassName().contains("hide")) { // view.getRelevanceExpression().addClassName("hide"); // } } public void show(final HeaderPresenter headerPresenter) { reset(); final FormClass formClass = headerPresenter.getFormClass(); view.setVisible(true); view.getLabel().setValue(Strings.nullToEmpty(formClass.getLabel())); view.getDescription().setValue(Strings.nullToEmpty(formClass.getDescription())); labelKeyUpHandler = view.getLabel().addKeyUpHandler(new KeyUpHandler() { @Override public void onKeyUp(KeyUpEvent event) { formClass.setLabel(view.getLabel().getValue()); headerPresenter.show(); } }); descriptionKeyUpHandler = view.getDescription().addKeyUpHandler(new KeyUpHandler() { @Override public void onKeyUp(KeyUpEvent event) { formClass.setDescription(view.getDescription().getValue()); headerPresenter.show(); } }); } }