All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.anwiba.commons.swing.object.DoubleIntervalField Maven / Gradle / Ivy

/*
 * #%L
 * anwiba commons swing
 * %%
 * Copyright (C) 2007 - 2016 Andreas Bartels
 * %%
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation, either version 2.1 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 Lesser Public License for more details.
 * 
 * You should have received a copy of the GNU General Lesser Public
 * License along with this program.  If not, see
 * .
 * #L%
 */
package net.anwiba.commons.swing.object;

import net.anwiba.commons.lang.functional.IConverter;
import net.anwiba.commons.logging.ILevel;
import net.anwiba.commons.logging.ILogger;
import net.anwiba.commons.logging.Logging;
import net.anwiba.commons.model.IChangeableObjectListener;
import net.anwiba.commons.model.IObjectDistributor;
import net.anwiba.commons.model.IObjectModel;
import net.anwiba.commons.model.ObjectModel;
import net.anwiba.commons.swing.utilities.SpringLayoutUtilities;
import net.anwiba.commons.utilities.interval.DoubleInterval;
import net.anwiba.commons.utilities.number.StringToDoubleConverter;
import net.anwiba.commons.utilities.validation.IValidationResult;
import net.anwiba.commons.utilities.validation.IValidator;

import java.text.MessageFormat;

import javax.swing.JComponent;
import javax.swing.JPanel;
import javax.swing.SpringLayout;

public class DoubleIntervalField implements IObjectField {

  private static ILogger logger = Logging.getLogger(DoubleIntervalField.class.getName());

  public static final class ValueValidator implements IValidator {
    private final double minimum;
    private final double maximum;
    StringToDoubleConverter converter = new StringToDoubleConverter();

    public ValueValidator(final double minimum, final double maximum) {
      this.minimum = minimum;
      this.maximum = maximum;
    }

    @Override
    public IValidationResult validate(final String string) {
      try {
        final Double valueObject = this.converter.convert(string);
        if (valueObject == null) {
          return IValidationResult.valid();
        }
        final double value = valueObject.doubleValue();
        final boolean isInBoundery = Double.isNaN(this.minimum)
            ? (Double.isNaN(this.maximum)
                ? true
                : value <= this.maximum)
            : Double.isNaN(this.maximum)
                ? this.minimum <= value
                : this.minimum <= value && value <= this.maximum;
        if (isInBoundery) {
          return IValidationResult.valid();
        }
        return IValidationResult.inValid(MessageFormat.format(
            "Value is out of bounderies ({0}, {1})",
            toString(this.minimum),
            toString(this.maximum)));
      } catch (final NumberFormatException exception) {
        return IValidationResult.inValid(exception.getLocalizedMessage());
      }
    }

    private String toString(final double value) {
      if (Double.isNaN(value)) {
        return "none";
      }
      return String.valueOf(value);
    }
  }

  private final IObjectModel validationModel;
  private final IObjectModel minimumValidationModel = new ObjectModel<>(IValidationResult.valid());
  private final IObjectModel maximumValidationModel = new ObjectModel<>(IValidationResult.valid());
  private final IObjectModel minimumValueModel = new ObjectModel<>();
  private final IObjectModel maximumValueModel = new ObjectModel<>();
  private final IObjectModel model;

  private JPanel component;
  private final double maximum;
  private final double minimum;
  private final IConverter toStringFormater;

  public DoubleIntervalField(
    final IConverter toStringFormater,
    final double minimum,
    final double maximum,
    final IObjectModel model,
    final IObjectModel validationModel) {
    this.model = model;
    this.minimum = minimum;
    this.maximum = maximum;
    this.toStringFormater = toStringFormater;
    this.validationModel = validationModel;
    final IObjectModel minimumValueModel = this.minimumValueModel;
    final IObjectModel maximumValueModel = this.maximumValueModel;
    minimumValueModel.set(model.get() == null
        ? null
        : Double.valueOf(model.get().getMinimum()));
    maximumValueModel.set(model.get() == null
        ? null
        : Double.valueOf(model.get().getMaximum()));
    final IObjectModel minimumValidationModel = this.minimumValidationModel;
    final IObjectModel maximumValidationModel = this.maximumValidationModel;
    validationModel.set(checkValid());
    final IChangeableObjectListener validationListener = new IChangeableObjectListener() {

      @SuppressWarnings("synthetic-access")
      @Override
      public void objectChanged() {
        logger.log(ILevel.DEBUG, "validation state changed"); //$NON-NLS-1$
        logger.log(ILevel.DEBUG, MessageFormat.format("minimum value: {0}", //$NON-NLS-1$
            (minimumValidationModel.get().isValid()
                ? "valid" //$NON-NLS-1$
                : MessageFormat.format("invalid: {0}", minimumValidationModel.get().getMessage())))); //$NON-NLS-1$
        logger.log(ILevel.DEBUG, "maximum value: " //$NON-NLS-1$
            + (maximumValidationModel.get().isValid()
                ? "valid" //$NON-NLS-1$
                : MessageFormat.format("invalid: {0}", maximumValidationModel.get().getMessage()))); //$NON-NLS-1$
        if (!minimumValidationModel.get().isValid()) {
          validationModel.set(IValidationResult.inValid("Illegal minimum value. "
              + minimumValidationModel.get().getMessage()));
          return;
        }
        if (!maximumValidationModel.get().isValid()) {
          validationModel.set(IValidationResult.inValid("Illegal maximum value. "
              + maximumValidationModel.get().getMessage()));
          return;
        }
        final IValidationResult validationResult = checkValid();
        if (validationResult.isValid()) {
          model.set(minimumValueModel.get() == null && maximumValueModel.get() == null
              ? null
              : new DoubleInterval(minimumValueModel.get().doubleValue(), maximumValueModel.get().doubleValue()));
        }
        validationModel.set(validationResult);
      }
    };
    minimumValidationModel.addChangeListener(validationListener);
    maximumValidationModel.addChangeListener(validationListener);
    model.addChangeListener(new IChangeableObjectListener() {

      @SuppressWarnings("synthetic-access")
      @Override
      public void objectChanged() {
        logger.log(ILevel.DEBUG, MessageFormat.format("model changed: {0}", model.get())); //$NON-NLS-1$
        minimumValueModel.set(model.get() == null
            ? null
            : Double.valueOf(model.get().getMinimum()));
        maximumValueModel.set(model.get() == null
            ? null
            : Double.valueOf(model.get().getMaximum()));
      }
    });
    minimumValueModel.addChangeListener(new IChangeableObjectListener() {

      @SuppressWarnings("synthetic-access")
      @Override
      public void objectChanged() {
        logger.log(ILevel.DEBUG, MessageFormat.format("minimum model changed: {0}", minimumValueModel.get())); //$NON-NLS-1$
        final IValidationResult validationResult = checkValid();
        if (validationResult.isValid()) {
          model.set(minimumValueModel.get() == null && maximumValueModel.get() == null
              ? null
              : new DoubleInterval(minimumValueModel.get().doubleValue(), maximumValueModel.get().doubleValue()));
        }
        validationModel.set(validationResult);
      }
    });
    maximumValueModel.addChangeListener(new IChangeableObjectListener() {

      @SuppressWarnings("synthetic-access")
      @Override
      public void objectChanged() {
        logger.log(ILevel.DEBUG, MessageFormat.format("maximum model changed: {0}", maximumValueModel.get())); //$NON-NLS-1$
        final IValidationResult validationResult = checkValid();
        if (validationResult.isValid()) {
          model.set(minimumValueModel.get() == null && maximumValueModel.get() == null
              ? null
              : new DoubleInterval(minimumValueModel.get().doubleValue(), maximumValueModel.get().doubleValue()));
        }
        validationModel.set(validationResult);
      }
    });
  }

  protected IValidationResult checkValid() {
    if (((this.minimumValueModel.get() == null && this.maximumValueModel.get() == null) || ((this.minimumValueModel
        .get() != null && this.maximumValueModel.get() != null) && (this.minimumValueModel.get().doubleValue() < this.maximumValueModel
        .get()
        .doubleValue())))) {
      return IValidationResult.valid();
    }
    if (this.minimumValueModel.get() == null) {
      return IValidationResult.inValid("Missing minimum value.");
    }
    if (this.maximumValueModel.get() == null) {
      return IValidationResult.inValid("Missing maximum value.");
    }
    if (this.maximumValueModel.get().doubleValue() == this.minimumValueModel.get().doubleValue()) {
      return IValidationResult.inValid("Minimum value equals maximum value.");
    }
    return IValidationResult.inValid("Minimum value is larger than maximum value.");
  }

  @Override
  public JComponent getComponent() {
    if (this.component == null) {
      this.component = createComponent();
    }
    return this.component;
  }

  private JPanel createComponent() {
    final ValueValidator validator = new ValueValidator(this.minimum, this.maximum);
    final DoubleField minimumField = createDoubleField(this.minimumValueModel, this.minimumValidationModel, validator);
    final DoubleField maximumField = createDoubleField(this.maximumValueModel, this.maximumValidationModel, validator);
    @SuppressWarnings("serial")
    final JPanel panel = new JPanel(new SpringLayout()) {
      @Override
      public void requestFocus() {
        minimumField.getComponent().requestFocus();
      }
    };
    panel.add(minimumField.getComponent());
    panel.add(maximumField.getComponent());
    SpringLayoutUtilities.makeCompactGrid(panel, 2, 1, 0, 0, 6, 0);
    return panel;
  }

  private DoubleField createDoubleField(
      final IObjectModel valueModel,
      final IObjectModel validationModel,
      final ValueValidator validator) {
    final DoubleObjectFieldConfigurationBuilder builder = new DoubleObjectFieldConfigurationBuilder();
    builder.setModel(valueModel);
    builder.setValidStateModel(validationModel);
    builder.setValidator(validator);
    builder.setToStringConverter(this.toStringFormater);
    return new DoubleField(builder.build());
  }

  @Override
  public IObjectModel getModel() {
    return this.model;
  }

  @Override
  public IObjectDistributor getValidationResultDistributor() {
    return this.validationModel;
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy