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

net.grinder.console.swingui.IntegerField Maven / Gradle / Ivy

// Copyright (C) 2000 - 2011 Philip Aston
// All rights reserved.
//
// This file is part of The Grinder software distribution. Refer to
// the file LICENSE which is part of The Grinder distribution for
// licensing details. The Grinder distribution is available on the
// Internet at http://grinder.sourceforge.net/
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
// OF THE POSSIBILITY OF SUCH DAMAGE.

package net.grinder.console.swingui;

import java.awt.Toolkit;
import javax.swing.JTextField;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.text.AttributeSet;
import javax.swing.text.BadLocationException;
import javax.swing.text.PlainDocument;


/**
 * JTextField that only accepts integers within a particular range.
 *
 * @author Philip Aston
 */
class IntegerField extends JTextField {

  private static final Toolkit s_toolkit = Toolkit.getDefaultToolkit();
  private static final double s_log10 = Math.log(10);
  private final int m_minimumValue;
  private final int m_maximumValue;

  private static int log10(long x) {
    // The 1e-10 is a cosmological constant to account for FP
    // rounding errors that occur, e.g. for x=10.
    return (int)((Math.log(x) / s_log10) + 1e-10);
  }

  private static int maxFieldWidth(int minimumValue, int maximumValue) {
    final long min = minimumValue < 0 ? 10 * -minimumValue : minimumValue;
    final long max = maximumValue < 0 ? 10 * -maximumValue : maximumValue;

    return log10(Math.max(Math.abs(min), Math.abs(max))) + 1;
  }

  public IntegerField(int minimumValue, int maximumValue) {
    super(maxFieldWidth(minimumValue, maximumValue));

    if (minimumValue > maximumValue) {
      throw new IllegalArgumentException(
        "Minimum value exceeds maximum value");
    }

    m_minimumValue = minimumValue;
    m_maximumValue = maximumValue;

    setValue(m_minimumValue);
    setDocument(new FormattedDocument());
  }

  public int getValue() {

    try {
      return Integer.parseInt(getText());
    }
    catch (NumberFormatException e) {
      // Occurs if field is blank or "-".
      return m_minimumValue;
    }
  }

  public void setValue(int value) {

    if (value < m_minimumValue || value > m_maximumValue) {
      throw new IllegalArgumentException("Value out of bounds");
    }

    setText(Integer.toString(value));
  }

  /**
   * Extend {@code PlainDocument} to perform our checks.
   */
  public class FormattedDocument extends PlainDocument {

    public void insertString(int offset, String string,
                             AttributeSet attributeSet)
      throws BadLocationException {

      final String currentText = super.getText(0, getLength());

      final String result =
        currentText.substring(0, offset) + string +
        currentText.substring(offset);

      if (m_minimumValue >= 0 || !"-".equals(result)) {
        try {
          final int x = Integer.parseInt(result);

          if (x < m_minimumValue || x > m_maximumValue) {
            s_toolkit.beep();
            return;
          }
        }
        catch (NumberFormatException e) {
          s_toolkit.beep();
          return;
        }
      }

      super.insertString(offset, string, attributeSet);
    }
  }

  public void addChangeListener(final ChangeListener listener) {

    getDocument().addDocumentListener(new DocumentListener() {

        private void notifyChangeListener() {
          listener.stateChanged(new ChangeEvent(this));
        }

        public void changedUpdate(DocumentEvent e) {
          notifyChangeListener();
        }

        public void insertUpdate(DocumentEvent e) {
          notifyChangeListener();
        }

        public void removeUpdate(DocumentEvent e) {
          notifyChangeListener();
        }
      });
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy