/*
* ALMA - Atacama Large Millimiter Array
* (c) European Southern Observatory, 2002
* Copyright by ESO (in the framework of the ALMA collaboration)
* and Cosylab 2002, All rights reserved
*
* This library 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 library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*/
package com.cosylab.logging.settings;
import java.awt.GridBagLayout;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.util.regex.Pattern;
import javax.swing.JCheckBox;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.text.AbstractDocument;
import javax.swing.text.AttributeSet;
import javax.swing.text.BadLocationException;
import javax.swing.text.DocumentFilter;
import alma.acs.gui.util.threadsupport.EDTExecutor;
import com.cosylab.logging.engine.ExactFilter;
import com.cosylab.logging.engine.Filter;
import com.cosylab.logging.engine.InvalidFilterConstraintException;
import com.cosylab.logging.engine.MinMaxFilter;
/**
* Serves the purpose of filtering according to the integer value. Used by
* FilterParameterDialog. Creation date: (2/7/02 10:42:17 AM)
*
* @author:
*/
public class FilterIntegerPanel extends FilterParameterPanel {
/**
* The filter to
* <UL>
* <LI>accept only digits ({@link #digitsRegExp}
* <LI>Limit the size of the input string to 9 digits
* </UL>
*
* @author acaproni
* @since ACS 12.1
*/
private class FormattedIntDocFilter extends DocumentFilter {
/**
* The regular expression used to check if the user input
* contains only digits
*/
private final Pattern digitsRegExp = Pattern.compile("[0-9]*");
/**
* The max number of digits that the user can insert in the text field
*/
public final int maxNumOfDigits;
/**
* Constructor
*
* @param size
* The max number of digits that the user can insert in the
* text field
*/
public FormattedIntDocFilter(int size) {
this.maxNumOfDigits = size;
}
@Override
public void remove(FilterBypass fb, int offset, int length)
throws BadLocationException {
// Removing is always allowed
super.remove(fb, offset, length);
}
/**
* According to {@link DocumentFilter} documentation this method is called prior of
* insertion of a string.
* <P>
* We override to allow the insertion only at the condition described in the
* documentation of this class
* @see FormattedIntDocFilter
*/
@Override
public void insertString(FilterBypass fb, int offset, String string,
AttributeSet attr) throws BadLocationException {
if (string==null || string.isEmpty()) {
return;
}
if (
digitsRegExp.matcher(string).matches() &&
fb.getDocument().getLength()+string.length()<=maxNumOfDigits) {
super.insertString(fb, offset, string, attr);
}
}
/**
* According to {@link DocumentFilter} documentation this method is called prior of
* replacing a string in the text field with a text.
* The length of the string to replace is also passed as parameter.
* <P>
* We override to allow the insertion only at the condition described in the
* documentation of this class
* @see FormattedIntDocFilter
*/
@Override
public void replace(FilterBypass fb, int offset, int length,
String text, AttributeSet attrs) throws BadLocationException {
if (text==null || text.isEmpty()) {
return;
}
if (
digitsRegExp.matcher(text).matches() &&
fb.getDocument().getLength()+text.length()-length<=maxNumOfDigits) {
super.replace(fb, offset, length, text, attrs);
}
}
}
/**
* The text field to insert the minimum value
*/
private JTextField minimum;
/**
* The text field to insert the maximum value
*/
private JTextField maximum;
/**
* The text field to insert the exact value
*/
private JTextField exact;
protected JCheckBox minimumCheck;
protected JCheckBox maximumCheck;
protected JCheckBox exactCheck;
private JCheckBox notCheck; // NOT policy
/**
* All the integer text fields have the same properties:
* this method avoid code repetition.
*
* @param initialValue The initial value in the text field
* @return The JTextField
*
*/
private JTextField buildIntegerTextField(int initialValue) {
JTextField ret=new JTextField(""+initialValue);
ret.setColumns(10);
AbstractDocument document = (AbstractDocument) ret.getDocument();
document.setDocumentFilter(new FormattedIntDocFilter(9));
return ret;
}
private class MinmaxChecked implements ItemListener {
public void itemStateChanged(ItemEvent e) {
if (e.getStateChange() == ItemEvent.SELECTED)
FilterIntegerPanel.this.exactCheck.setSelected(false);
}
}
private class ExactChecked implements ItemListener {
public void itemStateChanged(ItemEvent e) {
if (e.getStateChange() == ItemEvent.SELECTED) {
FilterIntegerPanel.this.minimumCheck.setSelected(false);
FilterIntegerPanel.this.maximumCheck.setSelected(false);
}
}
}
/**
* Insert the method's description here. Creation date: (2/7/02 10:44:28 AM)
*/
protected void createComponents() {
EDTExecutor.instance().execute(new Runnable() {
@Override
public void run() {
MinmaxChecked mmc = new MinmaxChecked();
JPanel panelTop = new JPanel(new GridBagLayout());
add(panelTop, newConstraints(0, 4, 4, 4, 4));
notCheck = new JCheckBox("Discard entries matching this filter");
notCheck.setToolTipText("Keep/discard entries matching this filter");
panelTop.add(notCheck, newConstraints(0, 4, 4, 4, 4));
minimumCheck = new JCheckBox("Minimum value");
minimumCheck.addItemListener(mmc);
panelTop.add(minimumCheck, newConstraints(1, 4, 0, 0, 0));
minimum = buildIntegerTextField(1);
panelTop.add(minimum, newConstraints(2, 0, 0, 4, 0));
maximumCheck = new JCheckBox("Maximum value");
maximumCheck.addItemListener(mmc);
panelTop.add(maximumCheck, newConstraints(3, 4, 0, 0, 0));
maximum = buildIntegerTextField(2);
panelTop.add(maximum, newConstraints(4, 0, 0, 4, 0));
JPanel panelBottom = new JPanel(new GridBagLayout());
add(panelBottom, newConstraints(1, 4, 4, 4, 4));
exactCheck = new JCheckBox("Exact value");
exactCheck.addItemListener(new ExactChecked());
panelBottom.add(exactCheck, newConstraints(0, 4, 0, 0, 0));
exact = buildIntegerTextField(1);
panelBottom.add(exact, newConstraints(1, 0, 0, 4, 0));
}
});
}
/**
* Insert the method's description here. Creation date: (2/7/02 11:08:31 AM)
*
* @return com.cosylab.logging.engine.Filter
* @exception com.cosylab.logging.settings.FilterParameterException
* The exception description.
*/
public Filter getFilter() throws FilterParameterException {
boolean bmin = minimumCheck.isSelected();
boolean bmax = maximumCheck.isSelected();
boolean bexact = exactCheck.isSelected();
Integer min = null;
Integer max = null;
if (bexact) {
try {
return new ExactFilter(getFieldIndex(), isLethal(),
Integer.parseInt(exact.getText()),
notCheck.isSelected());
} catch (InvalidFilterConstraintException e) {
throw new FilterParameterException(e.getMessage());
}
}
if (bmin) {
min = Integer.parseInt(minimum.getText());
}
if (bmax) {
max = Integer.parseInt(maximum.getText());
}
if ((min != null) && (max != null)) {
if (min.compareTo(max) > -1) {
throw new FilterParameterException(
"Minimum must be less than maximum");
}
}
try {
return new MinMaxFilter(getFieldIndex(), isLethal(), min, max,
notCheck.isSelected());
} catch (InvalidFilterConstraintException e) {
throw new FilterParameterException(e.getMessage());
}
}
/**
* Insert the method's description here. Creation date: (2/7/02 11:00:09 AM)
*
* @param f
* com.cosylab.logging.engine.Filter
*/
public void setFilter(Filter f) {
if (f == null)
return;
switch (f.getConstraint()) {
case EXACT:
setField(exactCheck, ((Number)((ExactFilter)f).getExact()).intValue(),exact);
break;
case MINIMUM:
setField(minimumCheck, ((Number)((MinMaxFilter)f).getMinimum()).intValue(),minimum);
break;
case MAXIMUM:
setField(maximumCheck, ((Number)((MinMaxFilter)f).getMaximum()).intValue(),maximum);
break;
case MINMAX:
setField(minimumCheck, ((Number)((MinMaxFilter)f).getMinimum()).intValue(),minimum);
setField(maximumCheck, ((Number)((MinMaxFilter)f).getMaximum()).intValue(),maximum);
break;
}
notCheck.setSelected(f.notPolicyApplyed());
}
/**
* Select the checkbox and set the value in the text field.
* <P>
* The same operation is repeated for the same check box and test field:
* this simple method avoids code repetition.
*
* @param checkBox The check box to select
* @param val The value to set in the text field
* @param textField The text field to set the value into
*/
private void setField(JCheckBox checkBox, int val, JTextField textField) {
if (checkBox==null) {
throw new IllegalArgumentException("The check box can't be null");
}
if (textField==null) {
throw new IllegalArgumentException("The text field can't be null");
}
if (val<0) {
throw new IllegalArgumentException("The value can't be less then 0! Rejected value is "+val);
}
checkBox.setSelected(true);
textField.setText(""+val);
}
}