/*
* Copyright 2016 Red Hat, Inc. and/or its affiliates.
*
* 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.kie.workbench.common.stunner.bpmn.client.forms.fields.assignmentsEditor;
import java.io.IOException;
import java.util.Set;
import javax.annotation.PostConstruct;
import javax.enterprise.event.Event;
import javax.inject.Inject;
import com.google.gwt.event.dom.client.BlurEvent;
import com.google.gwt.event.dom.client.BlurHandler;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.KeyDownEvent;
import com.google.gwt.event.dom.client.KeyDownHandler;
import com.google.gwt.event.logical.shared.ValueChangeEvent;
import com.google.gwt.text.shared.Renderer;
import com.google.gwt.user.client.ui.Composite;
import org.gwtbootstrap3.client.ui.Button;
import org.gwtbootstrap3.client.ui.TextBox;
import org.gwtbootstrap3.client.ui.ValueListBox;
import org.gwtbootstrap3.client.ui.constants.IconType;
import org.jboss.errai.databinding.client.api.DataBinder;
import org.jboss.errai.ui.shared.api.annotations.AutoBound;
import org.jboss.errai.ui.shared.api.annotations.Bound;
import org.jboss.errai.ui.shared.api.annotations.DataField;
import org.jboss.errai.ui.shared.api.annotations.EventHandler;
import org.jboss.errai.ui.shared.api.annotations.Templated;
import org.kie.workbench.common.stunner.bpmn.client.StunnerSpecific;
import org.kie.workbench.common.stunner.bpmn.client.forms.fields.i18n.StunnerFormsClientFieldsConstants;
import org.kie.workbench.common.stunner.bpmn.client.forms.fields.model.AssignmentRow;
import org.kie.workbench.common.stunner.bpmn.client.forms.fields.model.Variable.VariableType;
import org.kie.workbench.common.stunner.bpmn.client.forms.util.ListBoxValues;
import org.kie.workbench.common.stunner.bpmn.client.forms.widgets.ComboBox;
import org.kie.workbench.common.stunner.bpmn.client.forms.widgets.ComboBoxView;
import org.kie.workbench.common.stunner.bpmn.client.forms.widgets.VariableNameTextBox;
import org.uberfire.workbench.events.NotificationEvent;
/**
* A templated widget that will be used to display a row in a table of
* {@link AssignmentRow}s.
* <p/>
* The Name field of AssignmentRow is Bound, but other fields are not bound because
* they use a combination of ListBox and TextBox to implement a drop-down combo
* to hold the values.
*/
@Templated("ActivityDataIOEditorWidget.html#assignment")
public class AssignmentListItemWidgetViewImpl extends Composite implements AssignmentListItemWidgetView,
ComboBoxView.ModelPresenter {
/**
* Errai's data binding module will automatically bind the provided instance
* of the model (see {@link #setModel(AssignmentRow)}) to all fields annotated
* with {@link Bound}. If not specified otherwise, the bindings occur based on
* matching field names (e.g. assignment.name will automatically be kept in
* sync with the data-field "name")
*/
@Inject
@AutoBound
protected DataBinder<AssignmentRow> assignment;
@Inject
@Bound
@DataField
@StunnerSpecific
protected VariableNameTextBox name;
private boolean allowDuplicateNames = true;
private String duplicateNameErrorMessage = "";
@DataField
protected ValueListBox<String> dataType = new ValueListBox<String>(new Renderer<String>() {
public String render(final String object) {
String s = "";
if (object != null) {
s = object.toString();
}
return s;
}
public void render(final String object,
final Appendable appendable) throws IOException {
String s = render(object);
appendable.append(s);
}
});
@Inject
@DataField
protected TextBox customDataType;
@DataField
protected ValueListBox<String> processVar = new ValueListBox<String>(new Renderer<String>() {
public String render(final String object) {
String s = "";
if (object != null) {
s = object.toString();
}
return s;
}
public void render(final String object,
final Appendable appendable) throws IOException {
String s = render(object);
appendable.append(s);
}
});
@Inject
protected ComboBox dataTypeComboBox;
@Inject
ComboBox processVarComboBox;
@Inject
protected Event<NotificationEvent> notification;
@Inject
@DataField
protected TextBox constant;
@Inject
@DataField
protected Button deleteButton;
/**
* Widget the current assignment is in.
* Required for implementation of Delete button.
*/
private ActivityDataIOEditorWidget parentWidget;
public void setParentWidget(final ActivityDataIOEditorWidget parentWidget) {
this.parentWidget = parentWidget;
}
@Override
public void setTextBoxModelValue(final TextBox textBox,
final String value) {
if (textBox == customDataType) {
setCustomDataType(value);
} else if (textBox == constant) {
setConstant(value);
}
}
@Override
public void setListBoxModelValue(final ValueListBox<String> listBox,
final String value) {
if (listBox == dataType) {
setDataType(value);
} else if (listBox == processVar) {
setProcessVar(value);
}
}
@Override
public String getModelValue(final ValueListBox<String> listBox) {
if (listBox == dataType) {
String value = getCustomDataType();
if (value == null || value.isEmpty()) {
value = getDataType();
}
return value;
} else if (listBox == processVar) {
String value = getConstant();
if (value == null || value.isEmpty()) {
value = getProcessVar();
}
return value;
} else {
return "";
}
}
@PostConstruct
public void init() {
// Configure dataType and customDataType controls
dataTypeComboBox.init(this,
false,
dataType,
customDataType,
false,
true,
CUSTOM_PROMPT,
ENTER_TYPE_PROMPT);
// Configure processVar and constant controls
processVarComboBox.init(this,
false,
processVar,
constant,
true,
true,
CONSTANT_PROMPT,
ENTER_CONSTANT_PROMPT);
name.setRegExp("^[a-zA-Z0-9\\-\\.\\_]*$",
StunnerFormsClientFieldsConstants.INSTANCE.Removed_invalid_characters_from_name(),
StunnerFormsClientFieldsConstants.INSTANCE.Invalid_character_in_name());
customDataType.addKeyDownHandler(new KeyDownHandler() {
@Override
public void onKeyDown(KeyDownEvent event) {
int iChar = event.getNativeKeyCode();
if (iChar == ' ') {
event.preventDefault();
}
}
});
name.addBlurHandler(new BlurHandler() {
@Override
public void onBlur(BlurEvent event) {
if (!allowDuplicateNames) {
String value = name.getText();
if (isDuplicateName(value)) {
notification.fire(new NotificationEvent(duplicateNameErrorMessage,
NotificationEvent.NotificationType.ERROR));
name.setValue("");
ValueChangeEvent.fire(name,
"");
}
}
}
});
}
@Override
public AssignmentRow getModel() {
return assignment.getModel();
}
@Override
public void setModel(final AssignmentRow model) {
assignment.setModel(model);
initAssignmentControls();
}
@Override
public VariableType getVariableType() {
return getModel().getVariableType();
}
@Override
public String getDataType() {
return getModel().getDataType();
}
@Override
public void setDataType(final String dataType) {
getModel().setDataType(dataType);
}
@Override
public String getCustomDataType() {
return getModel().getCustomDataType();
}
@Override
public void setCustomDataType(final String customDataType) {
getModel().setCustomDataType(customDataType);
}
@Override
public String getProcessVar() {
return getModel().getProcessVar();
}
@Override
public void setProcessVar(final String processVar) {
getModel().setProcessVar(processVar);
}
@Override
public String getConstant() {
return getModel().getConstant();
}
@Override
public void setConstant(final String constant) {
getModel().setConstant(constant);
}
@Override
public void setDataTypes(final ListBoxValues dataTypeListBoxValues) {
dataTypeComboBox.setCurrentTextValue("");
dataTypeComboBox.setListBoxValues(dataTypeListBoxValues);
dataTypeComboBox.setShowCustomValues(true);
String cdt = getCustomDataType();
if (cdt != null && !cdt.isEmpty()) {
dataTypeComboBox.addCustomValueToListBoxValues(cdt,
"");
}
}
@Override
public void setProcessVariables(final ListBoxValues processVarListBoxValues) {
processVarComboBox.setCurrentTextValue("");
processVarComboBox.setListBoxValues(processVarListBoxValues);
String con = getConstant();
// processVar set here because the ListBoxValues must already have been set
if (con != null && !con.isEmpty()) {
String displayValue = processVarComboBox.addCustomValueToListBoxValues(con,
"");
processVar.setValue(displayValue);
}
}
@Override
public void setShowConstants(final boolean showConstants) {
processVarComboBox.setShowCustomValues(showConstants);
}
@Override
public void setDisallowedNames(final Set<String> disallowedNames,
final String disallowedNameErrorMessage) {
name.setInvalidValues(disallowedNames,
false,
disallowedNameErrorMessage);
}
@Override
public void setAllowDuplicateNames(final boolean allowDuplicateNames,
final String duplicateNameErrorMessage) {
this.allowDuplicateNames = allowDuplicateNames;
this.duplicateNameErrorMessage = duplicateNameErrorMessage;
}
@Override
public boolean isDuplicateName(final String name) {
return parentWidget.isDuplicateName(name);
}
@EventHandler("deleteButton")
public void handleDeleteButton(final ClickEvent e) {
parentWidget.removeAssignment(getModel());
}
/**
* Updates the display of this row according to the state of the
* corresponding {@link AssignmentRow}.
*/
private void initAssignmentControls() {
deleteButton.setIcon(IconType.TRASH);
if (getVariableType() == VariableType.OUTPUT) {
constant.setVisible(false);
}
String cdt = getCustomDataType();
if (cdt != null && !cdt.isEmpty()) {
customDataType.setValue(cdt);
dataType.setValue(cdt);
} else if (getDataType() != null) {
dataType.setValue(getDataType());
}
String con = getConstant();
if (con != null && !con.isEmpty()) {
// processVar ListBox is set in setProcessVariables because its ListBoxValues are required
constant.setValue(con);
} else if (getProcessVar() != null) {
processVar.setValue(getProcessVar());
}
}
public void notifyModelChanged() {
// Ignore
}
}