/*
 * @(#)ProgressSlider.java  1.0  1999-10-19
 *
 * Copyright (c) 1999 Werner Randelshofer, Immensee, Switzerland.
 * All rights reserved.
 *
 * You may not use, copy or modify this file, except in compliance with the
 * license agreement you entered into with Werner Randelshofer.
 * For details see accompanying license terms.
 */
package ch.randelshofer.gui;

import javax.swing.JSlider;
import javax.swing.BoundedRangeModel;
import javax.swing.SwingUtilities;

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

import java.io.Serializable;

/**
 * Combination of ProgressBar and Slider. Uses two BoundedRangeModels as model:
 * one for the slider and one for the progress bar.
 *
 * Supports asynchronous updates of the BoundedRangeModel.
 *
 * @author  Werner Randelshofer, Hausmatt 10, CH-6405 Immensee, Switzerland
 * @version  1.0  1999-10-19
 */
public class ProgressSlider
extends JSlider {
    private BoundedRangeModel progressModel_;
    
    public void setProgressModel(BoundedRangeModel m) {
        BoundedRangeModel oldModel = getProgressModel();
        
        if (progressModel_ != null) { 
            progressModel_.removeChangeListener(changeListener); 
        }
        progressModel_ = m;
        if (progressModel_ != null) {
            progressModel_.addChangeListener(changeListener);
      /*
      if (accessibleContext != null)
        {
        accessibleContext.firePropertyChange(
          AccessibleContext.ACCESSIBLE_VALUE_PROPERTY,
          (oldModel == null
          ? null : new Integer(oldModel.getValue())),
          (newModel == null
          ? null : new Integer(newModel.getValue())));
        }
       */
        }
        
        firePropertyChange("progressModel", oldModel, m);
    }
    public void setSliderModel(BoundedRangeModel m)
    { setModel(m); }
    
    public BoundedRangeModel getProgressModel()
    { return progressModel_; }
    
    public BoundedRangeModel getSliderModel()
    { return getModel(); }
    
    /**
     * We pass Change events along to the listeners with the
     * slider (instead of the model itself) as the event source.
     */
    private class ChngLstnr
    implements ChangeListener, Serializable, Runnable {
        public void stateChanged(ChangeEvent e) {
            if (SwingUtilities.isEventDispatchThread())
            { run(); }
            else {
                SwingUtilities.invokeLater(this);
            }
        }
        
        public void run() {
            ProgressSlider.this.fireStateChanged();
        }
    }
    
    protected void fireStateChanged() {
        super.fireStateChanged();
    }
    
    /**
     * Subclasses that want to handle model ChangeEvents differently
     * can override this method to return their own ChangeListener
     * implementation.  The default ChangeListener just forwards
     * ChangeEvents to the ChangeListeners added directly to the slider.
     *
     * @see #fireStateChanged
     */
    protected ChangeListener createChangeListener() {
        return new ChngLstnr();
    }
}
