private void doLayout() {
    layout.clear();

    for (int i = 0; i < model.getFieldValues().length; i++) {
      ActionFieldValue val = model.getFieldValues()[i];

      layout.setWidget(i, 0, getSetterLabel());
      layout.setWidget(i, 1, fieldSelector(val));
      layout.setWidget(i, 2, valueEditor(val));
      final int idx = i;
      Image remove = GuidedRuleEditorImages508.INSTANCE.DeleteItemSmall();
      remove.addClickHandler(
          new ClickHandler() {

            public void onClick(ClickEvent event) {
              if (Window.confirm(Constants.INSTANCE.RemoveThisItem())) {
                model.removeField(idx);
                setModified(true);
                getModeller().refreshWidget();

                // Signal possible change in Template variables
                TemplateVariablesChangedEvent tvce =
                    new TemplateVariablesChangedEvent(getModeller().getModel());
                getEventBus().fireEventFromSource(tvce, getModeller().getModel());
              }
            }
          });
      if (!this.readOnly) {
        layout.setWidget(i, 3, remove);
      }
    }

    if (model.getFieldValues().length == 0) {
      HorizontalPanel h = new HorizontalPanel();
      h.add(getSetterLabel());
      if (!this.readOnly) {
        Image image = GuidedRuleEditorImages508.INSTANCE.Edit();
        image.setAltText(Constants.INSTANCE.AddFirstNewField());
        image.setTitle(Constants.INSTANCE.AddFirstNewField());
        image.addClickHandler(
            new ClickHandler() {

              public void onClick(ClickEvent sender) {
                showAddFieldPopup(sender);
              }
            });
        h.add(image);
      }
      layout.setWidget(0, 0, h);
    }

    // layout.setWidget( 0, 1, inner );

  }
  /** Wraps a RuleModellerWidget with an icon to delete the pattern */
  private Widget wrapLHSWidget(final CompositeFactPattern model, int i, RuleModellerWidget w) {
    DirtyableHorizontalPane horiz = new DirtyableHorizontalPane();

    final Image remove = GuidedRuleEditorImages508.INSTANCE.DeleteItemSmall();
    remove.setTitle(
        Constants.INSTANCE.RemoveThisENTIREConditionAndAllTheFieldConstraintsThatBelongToIt());
    final int idx = i;
    remove.addClickHandler(
        new ClickHandler() {

          public void onClick(ClickEvent event) {
            if (Window.confirm(Constants.INSTANCE.RemoveThisEntireConditionQ())) {
              if (pattern.removeFactPattern(idx)) {
                getModeller().refreshWidget();
              }
            }
          }
        });

    horiz.setWidth("100%");
    w.setWidth("100%");

    horiz.add(w);
    if (!(getModeller().lockLHS() || w.isReadOnly())) {
      horiz.add(remove);
    }

    return horiz;
  }
  protected void showAddFieldPopup(ClickEvent w) {
    final DataModelOracle completions = this.getModeller().getSuggestionCompletions();
    final FormStylePopup popup =
        new FormStylePopup(
            GuidedRuleEditorImages508.INSTANCE.Wizard(), Constants.INSTANCE.AddAField());

    final ListBox box = new ListBox();
    box.addItem("...");

    for (int i = 0; i < fieldCompletions.length; i++) {
      box.addItem(fieldCompletions[i]);
    }

    box.setSelectedIndex(0);

    popup.addAttribute(Constants.INSTANCE.AddField(), box);
    box.addChangeHandler(
        new ChangeHandler() {

          public void onChange(ChangeEvent event) {
            String fieldName = box.getItemText(box.getSelectedIndex());

            String fieldType = completions.getFieldType(variableClass, fieldName);
            model.addFieldValue(new ActionFieldValue(fieldName, "", fieldType));
            setModified(true);
            getModeller().refreshWidget();
            popup.hide();
          }
        });

    popup.show();
  }
  protected Widget addRemoveButton(Widget w, ClickHandler listener) {
    DirtyableHorizontalPane horiz = new DirtyableHorizontalPane();

    final Image remove = GuidedRuleEditorImages508.INSTANCE.DeleteItemSmall();
    remove.setAltText(Constants.INSTANCE.RemoveThisBlockOfData());
    remove.setTitle(Constants.INSTANCE.RemoveThisBlockOfData());
    remove.addClickHandler(listener);

    horiz.setWidth("100%");
    w.setWidth("100%");

    horiz.add(w);
    if (!this.readOnly) {
      horiz.add(remove);
    }
    return horiz;
  }