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

org.wings.SSpinner Maven / Gradle / Ivy

The newest version!
/*
 * SSpinner.java
 *
 * Created on 31. August 2006, 09:21
 *
 * To change this template, choose Tools | Template Manager
 * and open the template in the editor.
 */

package org.wings;

import java.text.DecimalFormat;
import java.text.DateFormat;
import java.text.SimpleDateFormat;

import javax.swing.SpinnerModel;
import javax.swing.SpinnerDateModel;
import javax.swing.SpinnerNumberModel;
import javax.swing.SpinnerListModel;

import javax.swing.event.ChangeListener;
import javax.swing.event.ChangeEvent;

import org.wings.text.SDefaultFormatter;
import org.wings.text.SNumberFormatter;
import org.wings.text.SDateFormatter;
import org.wings.text.SDefaultFormatterFactory;

/**
 * A single line input field that lets the user select a number or an object value from an ordered sequence.
 * @author erik
 */
public class SSpinner extends SComponent implements LowLevelEventListener {
    
    private SpinnerModel    model;
    private DefaultEditor   editor;

    private ChangeListener  modelChangeListener = null;
    
    /**
     * @see LowLevelEventListener#isEpochCheckEnabled()
     */
    protected boolean epochCheckEnabled = true;
    
    /** Creates a new instance of SSpinner */
    public SSpinner() {
        this ( new SpinnerNumberModel(0, null, null, 1) );
    }
    
    /**
     * Creates a new instance of SSpinner
     * @param model the model for this Component
     */
    public SSpinner(SpinnerModel model) {
        this.model  = model;
        this.editor = createEditor( model );
    }
    
    protected DefaultEditor createEditor(SpinnerModel model) {
        DefaultEditor defaultEditor = null;
        
        if (model instanceof SpinnerNumberModel) {
	    defaultEditor = new NumberEditor(this);
        } else if (model instanceof SpinnerDateModel) {
	    defaultEditor = new DateEditor(this);
        } else if (model instanceof SpinnerListModel) {
	    defaultEditor = new ListEditor(this);
	} else {
	    defaultEditor = new DefaultEditor(this);
	}
        
        return defaultEditor;
    }
   
    /**
     * Returns the model of this Component.
     * @return the model of this Component
     */
    public SpinnerModel getModel() {
	return model;
    }
    
    /**
     * Sets the model for this Component.
     * @param model the model for this Component
     */
    public void setModel( SpinnerModel model ) {
        if ( !model.equals( this.model ) ) {
            SpinnerModel oldVal = this.model;
            this.model = model;
            if ( modelChangeListener != null ) {
                this.model.addChangeListener( modelChangeListener );
            }
            propertyChangeSupport.firePropertyChange("model", oldVal, this.model);
        }
    }
    
    /**
     * Returns the currrent value of this Component.
     * @return the current value of this Component
     */
    public Object getValue() {
        return model.getValue();
    }

    /**
     * Sets the current value for this Component.
     * @param value the new current value for this Component
     */
    public void setValue(Object value) {
        if ( value instanceof Long ) {
            if ( this.getValue() instanceof Integer ) {
                value = ((Long) value).intValue();
            } else if ( this.getValue() instanceof Double ) {
                value = ((Long) value).doubleValue();
            }
        }
        Object oldVal = model.getValue();
        model.setValue(value);
        propertyChangeSupport.firePropertyChange("value", oldVal, model.getValue());
    }
    
    /**
     * Returns the next value in the sequence.
     * @return the next value in the sequence
     */
    public Object getNextValue() {
        return model.getNextValue();
    }
    
    /**
     * Returns the current editor.
     * As long as wings donesn't support incremental updates for all components 
     * we have to return a DefaultEditor instead of SComponent.
     * @return DefaultEditor
     */
    public DefaultEditor getEditor() {
	return editor;
    }
    
    /**
     * Sets the editor for this Component.
     * @param editor the editor for this Component
     */
    public void setEditor(DefaultEditor editor) {
		if (editor != null && !editor.equals(this.editor) ) {
	        DefaultEditor oldVal = this.editor;
	        if (this.editor != null) {
		        this.editor.dismiss( this );
	            this.editor.setRecursivelyVisible(false);
	        }
		    this.editor = editor;
	        if (this.editor != null) {
	            this.editor.setRecursivelyVisible(isRecursivelyVisible());
	            this.editor.setEnabled(isEnabled());
	        }
	
	        propertyChangeSupport.firePropertyChange("editor", oldVal, this.editor);
	    }
    }

    @Override
    protected void setRecursivelyVisible(boolean recursivelyVisible) {
        super.setRecursivelyVisible(recursivelyVisible);
        if (editor != null)
            editor.setRecursivelyVisible(recursivelyVisible);
    }
    
    @Override
    public void setEnabled(boolean enabled) {
    	super.setEnabled(enabled);
        if (editor != null)
            editor.setEnabled(enabled);
    }

    public void addChangeListener( ChangeListener changeListener ) {
        addEventListener( ChangeListener.class, changeListener );
        
        if ( modelChangeListener == null ) {
            modelChangeListener = e -> {
                fireChangeEvents();
                propertyChangeSupport.firePropertyChange("stateChanged", "old", "new");
            };
            model.addChangeListener( modelChangeListener );
        }
    }
    
    private void fireChangeEvents() {
        ChangeListener[] listeners = getChangeListeners();
        for (ChangeListener listener : listeners) {
            listener.stateChanged(new ChangeEvent(this));
        }
    }

    public void removeChangeListener( ChangeListener changeListener ) {
        removeEventListener( ChangeListener.class, changeListener );
    }
 
    public ChangeListener[] getChangeListeners() {
        return (ChangeListener[])getListeners( ChangeListener.class );
    }
    
    public static class DefaultEditor extends SPanel implements ChangeListener {
        
        private SFormattedTextField ftf = null;
        private SSpinner spinner = null;
        
	public DefaultEditor(SSpinner spinner) {
	    super(null);
            
            this.spinner = spinner;
            putClientProperty("drm:realParentComponent", spinner);

            ftf = new SFormattedTextField( spinner.getValue() ) {
                @Override
                public void processLowLevelEvent(String action, String... values) {
                    String text = getText();
                    super.processLowLevelEvent( action, values );
                    SSpinner spinner = getSpinner();
                    if (isEditable() && isEnabled() && spinner != null ) {
                        if ( text == null || !text.equals( values[0] ) ) {
                            
                            Object lastValue = spinner.getValue();
                            try {
                                spinner.setValue( getTextField().getValue() );
                            } catch (IllegalArgumentException iae) {
                                try {
                                    getTextField().setValue(lastValue);
                                } catch (IllegalArgumentException iae2) {
                                }
                            }
                            
                        }
                    }
                    
                }
            };
            ftf.setStyle( "SFormattedTextField" );
            ftf.setHorizontalAlignment(SConstants.RIGHT);
            
            spinner.addChangeListener( this );
            
	    String toolTipText = spinner.getToolTipText();
	    if (toolTipText != null) {
		ftf.setToolTipText(toolTipText);
	    }

	    add(ftf);

	}
        
        public void dismiss( SSpinner s ) {
            spinner = null;
            s.removeChangeListener( this );
        }
        
        /**
         * Returns the SFormattedTextField of this editor
         * @return the SFormattedTextField of this editor
         */
        public SFormattedTextField getTextField() {
		    return ftf;
		}
        
        /**
         * Returns the Spinner of this editor.
         * @return the Spinner of this editor
         */
        public SSpinner getSpinner() {
            return this.spinner;
        }
        
        @Override
        public void setEnabled(boolean enabled) {
        	super.setEnabled(enabled);
            ftf.setEnabled(enabled);
        }

        @Override
        public void stateChanged(ChangeEvent event) {
            Object source = event.getSource();
            if ( source instanceof SSpinner ) {
                getTextField().setValue( ((SSpinner)source).getValue() );
            }
        }    
        
    }
      
    public static class NumberEditor extends DefaultEditor 
    {

        public NumberEditor(SSpinner spinner) {
            this( spinner, getPattern() );
        }
        
	public NumberEditor(SSpinner spinner, String decimalFormatPattern) {
	    this(spinner, new DecimalFormat(decimalFormatPattern));            
	}
        
        private NumberEditor(SSpinner spinner, DecimalFormat format) {
	    super(spinner);
	    if (!(spinner.getModel() instanceof SpinnerNumberModel)) {
		throw new IllegalArgumentException(
                          "model not a SpinnerNumberModel");
	    }
 
	    SDefaultFormatterFactory factory = new SDefaultFormatterFactory( new SNumberFormatter( format ) );
            
	    SFormattedTextField ftf = getTextField();
                ftf.setFormatterFactory(factory);
	}
        
        private static String getPattern() {
            DecimalFormat decimalFormat = new DecimalFormat();
            String pattern = decimalFormat.toPattern() + ";-" + decimalFormat.toPattern();
            return pattern;
        }
    }
    
    public static class DateEditor extends DefaultEditor 
    {
        
	public DateEditor(SSpinner spinner) {
            this(spinner, getPattern());
	}
        
	public DateEditor(SSpinner spinner, String dateFormatPattern) {
	    this(spinner, new SimpleDateFormat(dateFormatPattern,
                                               spinner.getSession().getLocale()));
	}

	private DateEditor(SSpinner spinner, DateFormat format) {
	    super(spinner);
	    if (!(spinner.getModel() instanceof SpinnerDateModel)) {
		throw new IllegalArgumentException(
                                 "model not a SpinnerDateModel");
	    }

	    SDefaultFormatterFactory factory = new SDefaultFormatterFactory( new SDateFormatter( format ) );

	    SFormattedTextField ftf = getTextField();
                ftf.setFormatterFactory(factory);

        }
        
        private static String getPattern() {
            SimpleDateFormat sdf = new SimpleDateFormat();
            return sdf.toPattern();
        }

	public SimpleDateFormat getFormat() {
	    return (SimpleDateFormat)((SDateFormatter)(getTextField().getFormatter())).getFormat();
	}
        
        /**
         * Returns the SpinnerDateModel of this editor.
         * @return the SpinnerDateModel of this editor
         */
	public SpinnerDateModel getModel() {
	    return (SpinnerDateModel)(getSpinner().getModel());
	}
    }
    
    public static class ListEditor extends DefaultEditor 
    {

	public ListEditor(SSpinner spinner) {
	    super(spinner);
	    if (!(spinner.getModel() instanceof SpinnerListModel)) {
		throw new IllegalArgumentException("model not a SpinnerListModel");
	    }
            
            SDefaultFormatterFactory factory = new SDefaultFormatterFactory( new SDefaultFormatter() );
            
            SFormattedTextField ftf = getTextField();
                ftf.setFormatterFactory(factory);
	}

        /**
         * Returns the SpinnerListModel of this editor.
         * @return the SpinnerListModel of this editor
         */
	public SpinnerListModel getModel() {
	    return (SpinnerListModel)(getSpinner().getModel());
	}

    }
    
    @Override
    protected void setParentFrame(SFrame f) {
        super.setParentFrame(f);
        editor.setParentFrame(f);
    }
   
    /**
     * @see LowLevelEventListener#isEpochCheckEnabled()
     */
    @Override
    public boolean isEpochCheckEnabled() {
        return epochCheckEnabled;
    }

    /**
     */
    public void setEpochCheckEnabled(boolean epochCheckEnabled) {
        boolean oldVal = this.epochCheckEnabled;
        this.epochCheckEnabled = epochCheckEnabled;
        propertyChangeSupport.firePropertyChange("epochCheckEnabled", oldVal, this.epochCheckEnabled);
    }
    
    /**
     * @see LowLevelEventListener#fireIntermediateEvents()
     */    
    @Override
    public void fireIntermediateEvents() {
    }
    
    /**
     * @see LowLevelEventListener#processLowLevelEvent(String action, String[] values)
     */        
    @Override
    public void processLowLevelEvent(String action, String... values) {
        processKeyEvents(values);
        if (action.endsWith("_keystroke"))
            return;
        
        int type = Integer.parseInt(values[0]);
        
        Object value = null;
        if ( type == 0 ) {
            value = model.getNextValue();
        } else {
            value = model.getPreviousValue();
        }
        try {
            model.setValue( value );
        } catch( IllegalArgumentException iae) {
        }
        
    }
    
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy