/*
 This file is part of the software framework JStatCom, 
 a library for building applications for data based analysis.

 Copyright (C) 2000-2005  Markus Kraetzig

 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.jstatcom.table;

import java.awt.Color;
import java.awt.Component;
import java.awt.event.FocusAdapter;
import java.awt.event.FocusEvent;
import java.awt.event.KeyEvent;

import javax.swing.DefaultCellEditor;
import javax.swing.JLabel;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.SwingConstants;
import javax.swing.border.LineBorder;
import javax.swing.table.TableCellEditor;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableModel;

import com.jstatcom.component.CompSettings;
import com.jstatcom.component.StdMessages;
import com.jstatcom.model.JSCData;
import com.jstatcom.model.JSCNArray;
import com.jstatcom.model.JSCTypeDef;
import com.jstatcom.model.JSCTypes;
import com.jstatcom.model.NumberRange;
import com.jstatcom.model.NumberRangeTypes;
import com.jstatcom.model.Symbol;
import com.jstatcom.model.SymbolTable;
import com.jstatcom.util.UString;

/**
 * JSCAbstractDataTable implementation for JSCNArray
 * data objects.
 * 
 * @author Markus Kraetzig 
 */
public class JSCNArrayTable extends JSCAbstractDataTable implements
        NumberDisplayTable {

    private int precision = 2;

    private boolean isModalDialogShowing = false;

    private NumberRange numberRange = new NumberRange(Double.NEGATIVE_INFINITY,
            Double.POSITIVE_INFINITY, NumberRangeTypes.OPEN);

    private final JTextField textField = new JTextField() {

        protected void processKeyEvent(KeyEvent e) {
            if (e.getKeyChar() == KeyEvent.VK_ESCAPE) {
                if (isEditing()) {
                    getCellEditor().cancelCellEditing();
                }
                e.consume();
            }
            super.processKeyEvent(e);
        }
    };

    private TableCellEditor doubleEditor = new DefaultCellEditor(textField) {
        private Double lastValue = null;

        public Component getTableCellEditorComponent(JTable table,
                Object value, boolean isSelected, int row, int column) {

            lastValue = (Double) value;
            textField.setHorizontalAlignment(SwingConstants.RIGHT);

            // set the text as it was rendered
            String text = value + "";

            TableCellRenderer renderer = table.getCellRenderer(row, column);
            Component comp = renderer.getTableCellRendererComponent(
                    JSCNArrayTable.this, value, isSelected, true, row, column);
            if (comp instanceof JLabel)
                text = ((JLabel) comp).getText();

            // make sure that the number is readable as a number in the editor
            if (UString.parseToNumber(text) != null)
                textField.setText(text);
            else
                textField.setText(lastValue + "");

            return editorComponent;

        }

        // input checking is done here
        public Object getCellEditorValue() {
            String text = ((String) super.getCellEditorValue()).trim();
            String error;
            Double val = UString.parseToNumber(text);
            if (val == null) {
                error = "Input \"" + text + "\" is not a valid number.";
                error = error + "\nThe previous value {" + lastValue
                        + "} is restored.";
                editorComp.setBackground(CompSettings.errorBackground);
                isModalDialogShowing = true;
                StdMessages.errorInput(error);
                isModalDialogShowing = false;

                editorComp.setBackground(Color.white);

                return lastValue;
            } else if (numberRange != null
                    && (error = numberRange.encloses(val.doubleValue())) != null) {
                editorComp.setBackground(CompSettings.errorBackground);
                isModalDialogShowing = true;

                StdMessages.errorInput(error + "\nThe previous value {"
                        + lastValue + "} is restored.");
                isModalDialogShowing = false;

                editorComp.setBackground(Color.white);
                return lastValue;
            } else
                return val;

        }

    };

    /**
     * Default constructor initializes this with a default model, renderer and
     * editor.
     */
    public JSCNArrayTable() {
        super();

        textField.setBorder(new LineBorder(Color.blue));
        setTablePopup(JSCPopupTypes.PRECISION);
        setDefaultEditor(Double.class, doubleEditor);
        setCellRenderer(JSCCellRendererTypes.DEFAULT);
        textField.addFocusListener(new FocusAdapter() {
            public void focusLost(FocusEvent evt) {
                // do not trigger again when focus lost
                // due to model error dialog
                if (isModalDialogShowing)
                    return;
                doubleEditor.stopCellEditing();
            }
        });

    }

    /*
     * @see com.jstatcom.component.JSCAbstractDataTable#setModelForJSCData(com.jstatcom.model.JSCData)
     */
    public void setModelForJSCData(JSCData data) {
        if (data == null) {
            JSCNArrayTableModel model = new JSCNArrayTableModel(null);
            model.setEditable(isEditable());
            setModel(model);
        } else {
            JSCNArrayTableModel model = new JSCNArrayTableModel(
                    new Symbol(data));
            model.setEditable(isEditable());
            setModel(model);
        }

    }

    /*
     * @see com.jstatcom.component.JSCAbstractDataTable#setModelForSymbolName(com.jstatcom.model.SymbolTable,
     *      String)
     */
    public void setModelForSymbolName(SymbolTable table, String name) {
        if (name == null || table == null) {
            JSCNArrayTableModel model = new JSCNArrayTableModel(null);
            model.setEditable(isEditable());
            setModel(model);

        } else {
            JSCNArrayTableModel model = new JSCNArrayTableModel(table
                    .get(new JSCTypeDef(name, JSCTypes.NARRAY)));
            model.setEditable(isEditable());
            setModel(model);

        }
    }

    /**
     * Returns the default table model object.
     * 
     * @return the default table model object
     */
    protected TableModel createDefaultDataModel() {
        return new JSCNArrayTableModel(null);
    }

    /**
     * Gets the number range to verify number input.
     * 
     * @return number range
     */
    public NumberRange getNumberRange() {
        return numberRange;
    }

    /**
     * Sets the number range to verify number input when cells are edited with
     * the default editor set for this table. It has no effect if the data is
     * set differently.
     * 
     * @param range
     *            the bounds to verify numbers against
     */
    public void setNumberRange(NumberRange range) {
        numberRange = range;
    }

    /**
     * Gets the precision for the number display.
     * 
     * @return precision for numbers
     */
    public int getPrecision() {
        return precision;
    }

    /**
     * Sets the precision for the number display. How numbers are rendered is
     * handled by the cell renderer.
     * 
     * @param precision
     */
    public void setPrecision(int precision) {
        this.precision = precision;
        // called to update the column width as well
        updateUI();
    }

    /**
     * Gets a reference of the underlying data object with the correct type.
     * 

* Usage note:
* The returned data is a reference to the underlying JSCData * object only until a new data object has been set. It should be used read * only. Changes that should not affect this table must be made on a copy of * the returned object. * * @return reference to data */ public JSCNArray getJSCNArray() { return (JSCNArray) getJSCData(); } }

Ads help maintain this website.