// create the GUI: How is this called? Well,ExampleComponentProvider tells MCT that SaveStateModel
  // is a view
  public SaveModelStateView(AbstractComponent ac, ViewInfo vi) {
    super(ac, vi);

    // This GUI allows a user to modify the component's data and persist it.
    TitledBorder titledBorder =
        BorderFactory.createTitledBorder(bundle.getString("ModelBorderTitle"));
    final JPanel jp = new JPanel();
    jp.setBorder(titledBorder);
    descriptionTextField = new JTextField();
    descriptionTextField.setText(mr.getData().getDataDescription());
    descriptionTextField.setToolTipText(bundle.getString("DescriptionToolTip"));
    doubleDataTextField = new JTextField(String.valueOf(mr.getData().getDoubleData()));
    doubleDataTextField.setText(String.valueOf(mr.getData().getDoubleData()));
    doubleDataTextField.setToolTipText(bundle.getString("ValueToolTip"));

    /*Purpose for DocumentListener: disable the save button for illegal inputs in the doubleDataTextField.
     * An illegal input is when the user enters a non-number.  Note: parse double
     * parses "-46.81d" as "-46.81d" (that is, it allows d, i, L, f at the end of
     * a number).  I wanted to disable the save button if the user enters any letter,
     * so that is why I first check if the text-field contains any letters before trying
     * to parse it as a double.
     */
    doubleDataTextField
        .getDocument()
        .addDocumentListener(
            new DocumentListener() {
              @Override
              public void removeUpdate(DocumentEvent e) {
                if (!saveButton.isEnabled()) saveButton.setEnabled(true);
                try {
                  if (containsLetters(doubleDataTextField.getText()))
                    throw new NumberFormatException();

                  Double.parseDouble(doubleDataTextField.getText());

                } catch (NumberFormatException s) {
                  saveButton.setEnabled(false);
                }
              }

              @Override
              public void insertUpdate(DocumentEvent e) {

                if (!saveButton.isEnabled()) saveButton.setEnabled(true);
                try {
                  if (containsLetters(doubleDataTextField.getText()))
                    throw new NumberFormatException();

                  Double.parseDouble(doubleDataTextField.getText());

                } catch (NumberFormatException s) {
                  saveButton.setEnabled(false);
                }
              }

              @Override
              public void changedUpdate(DocumentEvent e) {
                if (!saveButton.isEnabled()) saveButton.setEnabled(true);
                try {
                  if (containsLetters(doubleDataTextField.getText()))
                    throw new NumberFormatException();

                  Double.parseDouble(doubleDataTextField.getText());

                } catch (NumberFormatException s) {
                  saveButton.setEnabled(false);
                }
              }
            });

    jp.add(descriptionTextField);
    jp.add(doubleDataTextField);

    addToLayout(
        jp,
        bundle.getString("Description"),
        descriptionTextField,
        bundle.getString("Value"),
        doubleDataTextField,
        saveButton);

    saveButton.addActionListener(
        new ActionListener() {
          @Override
          public void actionPerformed(ActionEvent e) {
            AbstractComponent component = getManifestedComponent();

            mr.getData().setDoubleData(Double.parseDouble(doubleDataTextField.getText()));
            mr.getData().setDataDescription(descriptionTextField.getText());

            /*
             * Note that save() tells MCT that the user wishes to persist the data into the database.  Thus, when the user
             * clicks save, and then switches away from this view (like by choosing the info-view) MCT will prompt the user
             * if they wish to save the data.
             */
            component.save();
          }
        });

    // remember: MCT class 'View' extends a JPanel
    add(jp);
  }
 // This method is a callback from BaseComponent refreshViewManifestations().
 // Its job is to refresh all the GUI manifestations of this view role. In the case of updating the
 // model,
 // the refresh is done by copying new data from the model to the GUI visual elements.
 // In our example, the visual elements are a text field and a double value field.
 @Override
 public void updateMonitoredGUI() {
   ExampleModelRole mr = ExampleComponent.class.cast(getManifestedComponent()).getModel();
   doubleDataTextField.setText(String.valueOf(mr.getData().getDoubleData()));
   descriptionTextField.setText(mr.getData().getDataDescription());
 }