/* * Copyright 2014-2015 CyberVision, Inc. * * 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.kaaproject.avro.ui.gwt.client.widget; import static org.kaaproject.avro.ui.gwt.client.util.Utils.isBlank; import java.util.ArrayList; import java.util.List; import java.util.Map; import org.kaaproject.avro.ui.gwt.client.AvroUiResources.AvroUiStyle; import org.kaaproject.avro.ui.gwt.client.input.InputEvent; import org.kaaproject.avro.ui.gwt.client.input.InputEventHandler; import org.kaaproject.avro.ui.gwt.client.util.Utils; import org.kaaproject.avro.ui.gwt.client.widget.AlertPanel.Type; import org.kaaproject.avro.ui.gwt.client.widget.dialog.ConfirmDialog; import org.kaaproject.avro.ui.gwt.client.widget.dialog.ConfirmDialog.ConfirmListener; import org.kaaproject.avro.ui.gwt.client.widget.nav.NavigationActionListener; import org.kaaproject.avro.ui.gwt.client.widget.nav.NavigationContainer; import org.kaaproject.avro.ui.shared.AlertField; import org.kaaproject.avro.ui.shared.ArrayField; import org.kaaproject.avro.ui.shared.BooleanField; import org.kaaproject.avro.ui.shared.BytesField; import org.kaaproject.avro.ui.shared.DependenciesField; import org.kaaproject.avro.ui.shared.DoubleField; import org.kaaproject.avro.ui.shared.EnumField; import org.kaaproject.avro.ui.shared.FieldType; import org.kaaproject.avro.ui.shared.FixedField; import org.kaaproject.avro.ui.shared.FloatField; import org.kaaproject.avro.ui.shared.FormContext; import org.kaaproject.avro.ui.shared.FormContext.CtlDependenciesListener; import org.kaaproject.avro.ui.shared.FormContext.DeclaredTypesListener; import org.kaaproject.avro.ui.shared.FormEnum; import org.kaaproject.avro.ui.shared.FormField; import org.kaaproject.avro.ui.shared.FormField.ChangeListener; import org.kaaproject.avro.ui.shared.FormField.FieldAccess; import org.kaaproject.avro.ui.shared.FormField.ValueChangeListener; import org.kaaproject.avro.ui.shared.Fqn; import org.kaaproject.avro.ui.shared.FqnKey; import org.kaaproject.avro.ui.shared.FqnReferenceField; import org.kaaproject.avro.ui.shared.FqnVersion; import org.kaaproject.avro.ui.shared.IntegerField; import org.kaaproject.avro.ui.shared.LongField; import org.kaaproject.avro.ui.shared.RecordField; import org.kaaproject.avro.ui.shared.SizedField; import org.kaaproject.avro.ui.shared.StringField; import org.kaaproject.avro.ui.shared.StringField.InputType; import org.kaaproject.avro.ui.shared.UnionField; import org.kaaproject.avro.ui.shared.VersionField; import com.google.gwt.dom.client.Style.Position; import com.google.gwt.dom.client.Style.Unit; 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.ui.Button; import com.google.gwt.user.client.ui.CheckBox; import com.google.gwt.user.client.ui.FlexTable; import com.google.gwt.user.client.ui.FlowPanel; import com.google.gwt.user.client.ui.HTML; import com.google.gwt.user.client.ui.HasValue; import com.google.gwt.user.client.ui.HasVerticalAlignment; import com.google.gwt.user.client.ui.HasWidgets; import com.google.gwt.user.client.ui.HorizontalPanel; import com.google.gwt.user.client.ui.Label; import com.google.gwt.user.client.ui.SimplePanel; import com.google.gwt.user.client.ui.Widget; public abstract class AbstractFieldWidget<T extends FormField> extends SimplePanel implements HasValue<T>, ShowableWidget { private static final String DEFAULT_INTEGER_FORMAT = "#"; private static final String DEFAULT_DECIMAL_FORMAT = "#.#############################"; protected static final String FULL_WIDTH = "100%"; protected AvroWidgetsConfig config; protected List<HandlerRegistration> registrations = new ArrayList<HandlerRegistration>(); protected T value; protected NavigationContainer navigationContainer; protected final AvroUiStyle style; protected boolean readOnly = false; private static AvroUiStyle getDefaultStyle() { return Utils.avroUiStyle; } public AbstractFieldWidget(AvroWidgetsConfig config, NavigationContainer navigationContainer, boolean readOnly) { this(config, getDefaultStyle(), navigationContainer, readOnly); } public AbstractFieldWidget(AvroWidgetsConfig config, AvroUiStyle style, NavigationContainer navigationContainer, boolean readOnly) { this.config = config; this.navigationContainer = navigationContainer; this.readOnly = readOnly; // Inject the stylesheet. this.style = style; this.style.ensureInjected(); this.addStyleName(style.fieldWidget()); } @Override public HandlerRegistration addValueChangeHandler( ValueChangeHandler<T> handler) { return addHandler(handler, ValueChangeEvent.getType()); } @Override public T getValue() { return value; } @Override public void setValue(T value) { setValue(value, false); } @Override public void setValue(T value, boolean fireEvents) { if (value == this.value || (this.value != null && this.value.equals(value))) { return; } T before = this.value; this.value = value; updateFields(); if (fireEvents) { ValueChangeEvent.fireIfNotEqual(this, before, value); } } @Override protected void onUnload() { //clearRegistrations(); super.onUnload(); } public boolean validate() { return value != null && value.isValid(); } public void setReadOnly(boolean readOnly) { this.readOnly = readOnly; } @Override public void onShown() { traverseShown(this); } protected void clearRegistrations() { for (HandlerRegistration registration : registrations) { registration.removeHandler(); } registrations.clear(); } protected void traverseShown(HasWidgets hasWidgets) { for (Widget childWidget : hasWidgets) { if (childWidget instanceof ShowableWidget) { ((ShowableWidget)childWidget).onShown(); } else if (childWidget instanceof HasWidgets) { traverseShown((HasWidgets)childWidget); } else if (childWidget instanceof FieldWidgetPanel) { Widget w = ((FieldWidgetPanel)childWidget).getContent(); if (w instanceof ShowableWidget) { ((ShowableWidget)w).onShown(); } else if (w instanceof HasWidgets) { traverseShown((HasWidgets)w); } } } } public void updateConfig(AvroWidgetsConfig config) { this.config = config; traverseUpdateConfig(this, this.config); } private void traverseUpdateConfig(HasWidgets hasWidgets, AvroWidgetsConfig config) { for (Widget childWidget : hasWidgets) { if (childWidget instanceof AbstractFieldWidget) { ((AbstractFieldWidget<?>)childWidget).updateConfig(config); } else if (childWidget instanceof HasWidgets) { traverseUpdateConfig((HasWidgets)childWidget, config); } else if (childWidget instanceof FieldWidgetPanel) { Widget w = ((FieldWidgetPanel)childWidget).getContent(); if (w instanceof AbstractFieldWidget) { ((AbstractFieldWidget<?>)w).updateConfig(config); } else if (w instanceof HasWidgets) { traverseUpdateConfig((HasWidgets)w, config); } } } } protected void setNavigationContainer(NavigationContainer container) { this.navigationContainer = container; } protected void fireChanged() { ValueChangeEvent.fire(this, value); } protected void updateFields() { clearRegistrations(); setWidget(constructForm()); } protected abstract Widget constructForm(); protected void constructFormData(FlexTable table, FormField field, List<HandlerRegistration> handlerRegistrations) { table.removeAllRows(); if (field != null && field.getFieldAccess() != FieldAccess.HIDDEN) { int row = 0; if (field.getFieldType()==FieldType.RECORD) { RecordField recordField = ((RecordField)field); for (FormField formField : recordField.getValue()) { if (formField.getFieldAccess() != FieldAccess.HIDDEN) { row = constructField(table, row, formField, handlerRegistrations); row++; } } } else { constructField(table, row, field, handlerRegistrations); } } } private int constructField(FlexTable table, int row, FormField field, List<HandlerRegistration> handlerRegistrations) { int column = 0; Widget widget; if (shouldPlaceNestedWidgetButton(field.getFieldType())) { widget = constructNestedWidgetButton(field, handlerRegistrations); } else { widget = constructWidget(field, handlerRegistrations); } if (shouldPlaceLabel(field.getFieldType())) { constructLabel(table, field, row, column); column++; } row = placeWidget(table, field.getFieldType(), widget, row, column, handlerRegistrations); return row; } private boolean shouldPlaceLabel(FieldType type) { if (type.isComplex()) { if (type == FieldType.UNION) { return value.getFieldType() == FieldType.UNION; } else { return type != FieldType.ARRAY && type != FieldType.DEPENDENCIES; } } else { return type != FieldType.ALERT; } } protected boolean shouldPlaceNestedWidgetButton(FieldType type) { if (type.isComplex()) { if (type == FieldType.UNION) { return value.getFieldType() == FieldType.UNION; } else { return type != FieldType.ARRAY && type != FieldType.DEPENDENCIES; } } else { return false; } } protected int constructAndPlaceWidget(FlexTable table, FormField field, int row, int column, List<HandlerRegistration> handlerRegistrations) { Widget widget = constructWidget(field, handlerRegistrations); row = placeWidget(table, field.getFieldType(), widget, row, column, handlerRegistrations); return row; } protected int placeWidget(FlexTable table, FieldType type, Widget widget, int row, int column, List<HandlerRegistration> handlerRegistrations) { if (type.isComplex() && !shouldPlaceNestedWidgetButton(type)) { table.setText(row, 0, ""); table.setText(row, 1, ""); row++; table.setWidget(row, column, widget); table.getFlexCellFormatter().setColSpan(row, column, 3); } else { table.setWidget(row, column, widget); if (type == FieldType.ALERT) { table.getFlexCellFormatter().setColSpan(row, column, 2); } } return row; } protected Widget constructLabel(FlexTable table, FormField field, int row, int column) { FieldWidgetLabel label = new FieldWidgetLabel(field); table.setWidget(row, column, label); return label; } protected Widget constructWidget(FormField field, List<HandlerRegistration> handlerRegistrations) { Widget widget = null; if ((readOnly || field.isReadOnly()) && !field.getFieldType().isComplex()) { if (field.getFieldType() == FieldType.BOOLEAN) { widget = constructBooleanWidget((BooleanField)field, handlerRegistrations); } else { String text = extractStringValue(field); HTML textLabel = new HTML(" "); textLabel.setHeight(FULL_WIDTH); textLabel.setStyleName(style.secondaryLabel()); if (!isBlank(text)) { textLabel.setText(text); } widget = textLabel; } } else { switch (field.getFieldType()) { case STRING: widget = constructStringWidget((StringField)field, handlerRegistrations); break; case BYTES: widget = constructBytesWidget((BytesField)field, handlerRegistrations); break; case FIXED: widget = constructFixedWidget((FixedField)field, handlerRegistrations); break; case INT: widget = constructIntegerWidget((IntegerField)field, handlerRegistrations); break; case FLOAT: widget = constructFloatWidget((FloatField)field, handlerRegistrations); break; case DOUBLE: widget = constructDoubleWidget((DoubleField)field, handlerRegistrations); break; case LONG: widget = constructLongWidget((LongField)field, handlerRegistrations); break; case ENUM: widget = constructEnumWidget((EnumField)field, handlerRegistrations); break; case BOOLEAN: widget = constructBooleanWidget((BooleanField)field, handlerRegistrations); break; case ARRAY: widget = constructArrayWidget((ArrayField)field, handlerRegistrations); break; case RECORD: throw new RuntimeException("Can't create record widget inside table."); case UNION: widget = constructUnionWidget((UnionField)field, handlerRegistrations); break; case TYPE_REFERENCE: widget = constructFqnReferenceWidget((FqnReferenceField)field, handlerRegistrations); break; case ALERT: widget = constructAlertWidget((AlertField)field, handlerRegistrations); break; case VERSION: widget = constructVersionWidget((VersionField)field, handlerRegistrations); break; case DEPENDENCIES: widget = constructDependenciesWidget((DependenciesField)field, handlerRegistrations); break; } } widget.setWidth(FULL_WIDTH); return widget; } protected static String extractStringValue(FormField field) { switch (field.getFieldType()) { case STRING: return ((StringField)field).getValue(); case BYTES: return ((BytesField)field).getValue(); case FIXED: return ((FixedField)field).getValue(); case INT: Integer intVal = ((IntegerField)field).getValue(); return intVal != null ? String.valueOf(intVal) : null; case FLOAT: Float floatVal = ((FloatField)field).getValue(); return floatVal != null ? String.valueOf(floatVal) : null; case DOUBLE: Double doubleVal = ((DoubleField)field).getValue(); return doubleVal != null ? String.valueOf(doubleVal) : null; case LONG: Long longVal = ((LongField)field).getValue(); return longVal != null ? String.valueOf(longVal) : null; case ENUM: FormEnum enumVal = ((EnumField)field).getValue(); return enumVal != null ? enumVal.getDisplayValue() : null; case TYPE_REFERENCE: Fqn fqnVal = ((FqnReferenceField)field).getFqnValue(); return fqnVal != null ? fqnVal.getFqnString() : null; case VERSION: Integer versionVal = ((VersionField)field).getValue(); return versionVal != null ? String.valueOf(versionVal) : null; default: return ""; } } private Widget constructStringWidget(final StringField field, List<HandlerRegistration> handlerRegistrations) { final SizedTextBox textBox = new SizedTextBox(style, field.getInputType(), field.getDisplayPrompt(), field.getMaxLength(), true, field.getMaxLength() != SizedField.DEFAULT_MAX_LENGTH); textBox.setValue(field.getValue()); handlerRegistrations.add(textBox.addInputHandler(new InputEventHandler() { @Override public void onInputChanged(InputEvent event) { field.setValue(textBox.getValue()); fireChanged(); } })); return textBox; } private Widget constructBytesWidget(final BytesField field, List<HandlerRegistration> handlerRegistrations) { final SizedTextBox textBox = new SizedTextBox(style, InputType.PLAIN, field.getDisplayPrompt(), SizedField.DEFAULT_MAX_LENGTH, true, false); textBox.setValue(field.getValue()); handlerRegistrations.add(textBox.addInputHandler(new InputEventHandler() { @Override public void onInputChanged(InputEvent event) { field.setValue(textBox.getValue()); textBox.setInvalid(!field.isValid()); fireChanged(); } })); return textBox; } private Widget constructFixedWidget(final FixedField field, List<HandlerRegistration> handlerRegistrations) { final SizedTextBox textBox = new SizedTextBox(style, InputType.PLAIN, field.getDisplayPrompt(), field.getStringMaxSize(), true, false); textBox.setValue(field.getValue()); handlerRegistrations.add(textBox.addInputHandler(new InputEventHandler() { @Override public void onInputChanged(InputEvent event) { field.setValue(textBox.getValue()); textBox.setInvalid(!field.isValid()); fireChanged(); } })); return textBox; } private Widget constructIntegerWidget(final IntegerField field, List<HandlerRegistration> handlerRegistrations) { final IntegerBox integerBox = new IntegerBox(style, field.getDisplayPrompt(), DEFAULT_INTEGER_FORMAT); integerBox.setValue(field.getValue()); handlerRegistrations.add(integerBox.addKeyUpHandler(new KeyUpHandler() { @Override public void onKeyUp(KeyUpEvent event) { field.setValue(integerBox.getValue()); fireChanged(); } })); return integerBox; } private Widget constructLongWidget(final LongField field, List<HandlerRegistration> handlerRegistrations) { final LongBox longBox = new LongBox(style, field.getDisplayPrompt(), DEFAULT_INTEGER_FORMAT); longBox.setValue(field.getValue()); handlerRegistrations.add(longBox.addKeyUpHandler(new KeyUpHandler() { @Override public void onKeyUp(KeyUpEvent event) { field.setValue(longBox.getValue()); fireChanged(); } })); return longBox; } private Widget constructFloatWidget(final FloatField field, List<HandlerRegistration> handlerRegistrations) { final FloatBox floatBox = new FloatBox(style, field.getDisplayPrompt(), DEFAULT_DECIMAL_FORMAT); floatBox.setValue(field.getValue()); handlerRegistrations.add(floatBox.addKeyUpHandler(new KeyUpHandler() { @Override public void onKeyUp(KeyUpEvent event) { field.setValue(floatBox.getValue()); fireChanged(); } })); return floatBox; } private Widget constructDoubleWidget(final DoubleField field, List<HandlerRegistration> handlerRegistrations) { final DoubleBox doubleBox = new DoubleBox(style, field.getDisplayPrompt(), DEFAULT_DECIMAL_FORMAT); doubleBox.setValue(field.getValue()); handlerRegistrations.add(doubleBox.addKeyUpHandler(new KeyUpHandler() { @Override public void onKeyUp(KeyUpEvent event) { field.setValue(doubleBox.getValue()); fireChanged(); } })); return doubleBox; } private Widget constructFqnReferenceWidget(final FqnReferenceField field, List<HandlerRegistration> handlerRegistrations) { final FqnReferenceBox fqnBox = new FqnReferenceBox(field.getDisplayPrompt()); fqnBox.updateDeclaredFqns(field.getContext().getDeclaredTypes()); fqnBox.setValue(field.getValue()); final DeclaredTypesListener listener = new DeclaredTypesListener() { @Override public void onDeclaredTypesUpdated(Map<FqnKey, Fqn> declaredFqns) { if (fqnBox.isAttached()) { fqnBox.updateDeclaredFqns(declaredFqns); } } }; field.getContext().addDeclaredTypesListener(listener); final FormContext context = field.getContext(); HandlerRegistration handlerRegistration = new HandlerRegistration() { @Override public void removeHandler() { context.removeDeclaredTypesListener(listener); } }; handlerRegistrations.add(handlerRegistration); handlerRegistrations.add(fqnBox.addValueChangeHandler(new ValueChangeHandler<FqnKey>() { @Override public void onValueChange(ValueChangeEvent<FqnKey> event) { field.setValue(event.getValue()); fireChanged(); } })); return fqnBox; } private Widget constructAlertWidget(final AlertField field, List<HandlerRegistration> handlerRegistrations) { final AlertPanel alertPanel = new AlertPanel(Type.ERROR); alertPanel.getElement().getStyle().setMargin(5, Unit.PX); if (field.getValue() != null) { alertPanel.setMessage(field.getValue()); alertPanel.setVisible(true); } else { alertPanel.setMessage(""); alertPanel.setVisible(false); } final ValueChangeListener listener = new ValueChangeListener() { private static final long serialVersionUID = -4935107365199693997L; @Override public void onValueChanged(Object value) { if (value != null) { alertPanel.setMessage(value.toString()); alertPanel.setVisible(true); } else { alertPanel.setMessage(""); alertPanel.setVisible(false); } } }; field.addTransientValueChangeListener(listener); HandlerRegistration handlerRegistration = new HandlerRegistration() { @Override public void removeHandler() { field.removeTransientValueChangeListener(listener); } }; handlerRegistrations.add(handlerRegistration); return alertPanel; } private Widget constructVersionWidget(final VersionField field, List<HandlerRegistration> handlerRegistrations) { final IntegerBox integerBox = new IntegerBox(style, field.getDisplayPrompt(), DEFAULT_INTEGER_FORMAT); integerBox.setValue(field.getValue()); handlerRegistrations.add(integerBox.addKeyUpHandler(new KeyUpHandler() { @Override public void onKeyUp(KeyUpEvent event) { field.setValue(integerBox.getValue()); fireChanged(); } })); final ValueChangeListener listener = new ValueChangeListener() { private static final long serialVersionUID = -6240272895089248662L; @Override public void onValueChanged(Object value) { integerBox.setValue(field.getValue()); } }; field.addTransientValueChangeListener(listener); HandlerRegistration handlerRegistration = new HandlerRegistration() { @Override public void removeHandler() { field.removeTransientValueChangeListener(listener); } }; handlerRegistrations.add(handlerRegistration); return integerBox; } private Widget constructDependenciesWidget(final DependenciesField field, List<HandlerRegistration> handlerRegistrations) { final DependenciesFieldWidget widget = new DependenciesFieldWidget(config, style, navigationContainer, readOnly); widget.setValue(field); if (field.getValue() != null && !field.getValue().isEmpty()) { widget.setVisible(true); } else { widget.setVisible(false); } final CtlDependenciesListener listener = new CtlDependenciesListener() { @Override public void onCtlDependenciesUpdated( List<FqnVersion> ctlDependenciesList) { if (ctlDependenciesList != null && !ctlDependenciesList.isEmpty()) { widget.setVisible(true); widget.reload(); } else { widget.setVisible(false); } fireChanged(); } }; field.getContext().addCtlDependenciesListener(listener); HandlerRegistration handlerRegistration = new HandlerRegistration() { @Override public void removeHandler() { field.getContext().removeCtlDependenciesListener(listener); } }; handlerRegistrations.add(handlerRegistration); return widget; } private Widget constructEnumWidget(final EnumField field, List<HandlerRegistration> handlerRegistrations) { FormEnumListBox enumBox = new FormEnumListBox(style, field.getDisplayPrompt()); if (!field.isOptional() && !field.isOverride()) { enumBox.setValue(field.getValue()); } enumBox.setAcceptableValues(field.getEnumValues()); if (field.isOptional() || field.isOverride()) { enumBox.setValue(field.getValue()); } handlerRegistrations.add(enumBox.addValueChangeHandler(new ValueChangeHandler<FormEnum>() { @Override public void onValueChange(ValueChangeEvent<FormEnum> event) { field.setValue(event.getValue()); fireChanged(); } })); return enumBox; } private Widget constructBooleanWidget(final BooleanField field, List<HandlerRegistration> handlerRegistrations) { CheckBox checkBox = new CheckBox(); checkBox.setValue(field.getValue()); checkBox.setTitle(field.getDisplayPrompt()); checkBox.setEnabled(!readOnly && !field.isReadOnly()); if (!readOnly && !field.isReadOnly()) { handlerRegistrations.add(checkBox.addValueChangeHandler(new ValueChangeHandler<Boolean>() { @Override public void onValueChange(ValueChangeEvent<Boolean> event) { field.setValue(event.getValue()); fireChanged(); } })); } return checkBox; } private Widget constructArrayWidget(final ArrayField field, List<HandlerRegistration> handlerRegistrations) { ArrayFieldWidget arrayWidget = new ArrayFieldWidget(config, style, navigationContainer, readOnly); arrayWidget.setValue(field); if (!readOnly && !field.isReadOnly()) { handlerRegistrations.add(arrayWidget.addValueChangeHandler(new ValueChangeHandler<ArrayField>() { @Override public void onValueChange(ValueChangeEvent<ArrayField> event) { fireChanged(); } })); } return arrayWidget; } private Widget constructUnionWidget(final UnionField field, List<HandlerRegistration> handlerRegistrations) { UnionFieldWidget unionWidget = new UnionFieldWidget(config, style, navigationContainer, readOnly); unionWidget.setValue(field); if (!readOnly && !field.isReadOnly()) { handlerRegistrations.add(unionWidget.addValueChangeHandler(new ValueChangeHandler<UnionField>() { @Override public void onValueChange(ValueChangeEvent<UnionField> event) { fireChanged(); } })); } return unionWidget; } private Widget constructNestedWidgetButton(final FormField field, List<HandlerRegistration> handlerRegistrations) { HorizontalPanel nestedWidget = new HorizontalPanel(); nestedWidget.setVerticalAlignment(HasVerticalAlignment.ALIGN_MIDDLE); final String fieldTypeName = field.getFieldType().getName(); Label label = new Label(Utils.messages.nestedEntry(fieldTypeName)); Label emptyLabel = new Label(Utils.constants.empty()); label.setStyleName(style.fieldNotes()); label.getElement().getStyle().setPaddingRight(10, Unit.PX); final boolean isEmptyRecord = field.getFieldType() == FieldType.RECORD && field.isNull(); final Button openButton = new Button(isEmptyRecord ? Utils.constants.create() : Utils.constants.open()); openButton.addStyleName(style.buttonSmall()); final Button deleteButon = new Button(Utils.constants.delete()); deleteButon.addStyleName(style.buttonSmall()); deleteButon.getElement().getStyle().setMarginLeft(10, Unit.PX); boolean isReadOnly = readOnly || field.isReadOnly(); boolean showEmptyLabel = isReadOnly && field.isNull(); if (showEmptyLabel) { openButton.setVisible(false); deleteButon.setVisible(false); emptyLabel.setVisible(true); } else { openButton.setVisible(true); emptyLabel.setVisible(false); handlerRegistrations.add(openButton.addClickHandler(new ClickHandler() { @Override public void onClick(ClickEvent event) { if (field.getFieldType() == FieldType.RECORD && field.isNull()) { ((RecordField)field).create(); openButton.setText(Utils.constants.open()); deleteButon.setVisible(true); fireChanged(); } navigationContainer.showField(field, new NavigationActionListener() { @Override public void onChanged(FormField field) { fireChanged(); } @Override public void onAdded(FormField field) {} }); } })); handlerRegistrations.add(deleteButon.addClickHandler(new ClickHandler() { @Override public void onClick(ClickEvent event) { ConfirmListener listener = new ConfirmListener() { @Override public void onNo() { } @Override public void onYes() { ((RecordField)field).setNull(); openButton.setText(Utils.constants.create()); deleteButon.setVisible(false); fireChanged(); } }; ConfirmDialog dialog = new ConfirmDialog(listener, Utils.messages.deleteNestedEntryTitle(), Utils.messages.deleteNestedEntryQuestion(fieldTypeName, field.getDisplayName())); dialog.center(); dialog.show(); } })); deleteButon.setVisible(field.getFieldType() == FieldType.RECORD && !field.isNull() && !isReadOnly); } nestedWidget.add(label); nestedWidget.add(emptyLabel); nestedWidget.add(openButton); nestedWidget.add(deleteButon); return nestedWidget; } private class FieldWidgetLabel extends FlowPanel implements ChangeListener { private CheckBox overrideBox; public FieldWidgetLabel(final FormField field) { this.getElement().getStyle().setPosition(Position.RELATIVE); this.getElement().getStyle().setProperty("display", "flex"); Label label = new Label(field.getDisplayName()); if (field.isOverride()) { overrideBox = new CheckBox(); label.getElement().getStyle().setLeft(28, Unit.PX); overrideBox.setValue(field.isChanged()); overrideBox.setEnabled(!readOnly && !field.isReadOnly()); add(overrideBox); if (!readOnly && !field.isReadOnly()) { registrations.add(overrideBox.addValueChangeHandler(new ValueChangeHandler<Boolean>() { @Override public void onValueChange(ValueChangeEvent<Boolean> event) { field.setChanged(event.getValue(), true); fireChanged(); } })); field.addChangeListener(this); } } if (!field.isOptional()) { label.addStyleName(style.requiredField()); } add(label); } @Override public void onChanged(boolean changed) { overrideBox.setValue(changed); } } }