com.lawal.SliderBar.java Source code

Java tutorial

Introduction

Here is the source code for com.lawal.SliderBar.java

Source

/*
 * 
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 * 
 * http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 * 
 * 
 * This is a direct port of the Google gwt SliderBar into Vaadin obtained from
 * http://google-web-toolkit-incubator.googlecode.com/svn/trunk/demo/SliderBar/index.html
 * 
 * @author
 * talktolawal@gmail.com
 * 
 */
package com.lawal;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import com.lawal.SliderUtil.DateLabelFormat;
import com.vaadin.terminal.PaintException;
import com.vaadin.terminal.PaintTarget;
import com.vaadin.ui.AbstractField;

@SuppressWarnings("serial")
@com.vaadin.ui.ClientWidget(com.lawal.client.ui.VSliderBar.class)
public class SliderBar<T extends Number> extends AbstractField {

    public interface SliderValueListener<T> {
        public void sliderValuesChanged(T value);
    }

    /**
     * ValueOutOfBoundsException
     * 
     * @author IT Mill Ltd.
     */
    public static class ValueOutOfBoundsException extends Exception {
        private final Double _value;

        /**
         * Constructs an <code>ValueOutOfBoundsException</code> with the
         * specified detail message.
         * 
         * @param valueOutOfBounds
         */
        public ValueOutOfBoundsException(Double valueOutOfBounds) {
            _value = valueOutOfBounds;
        }

        public Double getValue() {
            return _value;
        }
    }

    private DateLabelFormat _dateLabelFormat = null;
    private Class<T> _numberClass;
    private List<SliderValueListener<T>> listeners = new ArrayList<SliderValueListener<T>>();
    private T max;
    private T min;
    private int numLabels = 10;
    private int numTicks = 10;
    private T stepSize;
    private boolean superImmediateMode = false;

    /**
     * Default Slider constructor. Sets all values to defaults and the slide
     * handle at minimum value.
     */
    @SuppressWarnings("unchecked")
    public SliderBar(Class<T> numberClass) {
        min = (T) SliderUtil.initValue(numberClass, 0);
        max = (T) SliderUtil.initValue(numberClass, 100);
        stepSize = (T) SliderUtil.initValue(numberClass, 1);

        _numberClass = numberClass;
        setListener();
        setInternalVal(new Double(min.doubleValue()));
    }

    private void setListener() {
        super.addListener(new ValueChangeListener() {

            @Override
            public void valueChange(com.vaadin.data.Property.ValueChangeEvent event) {
                fireValueChangeListeners();

            }
        });

    }

    /**
     * @param min
     * @param max
     * @param stepSize
     */
    public SliderBar(Class<T> numberClass, T min, T max, T stepsize) {
        this(numberClass);
        setMin(min);
        setMax(max);
        setStepSize(stepsize);
    }

    /*
     * @deprecated use {@link #addRangeValueListener(SliderValueListener)}
     * instead
     */
    @Override
    @Deprecated
    public void addListener(ValueChangeListener listener) {

        super.addListener(listener);
    }

    public void addRangeValueListener(SliderValueListener<T> listener) {
        listeners.add(listener);
    }

    /**
     * Invoked when the value of a variable has changed. SliderBar listeners are
     * notified if the slider value has changed.
     * 
     * @param source
     * @param variables
     */
    @Override
    public void changeVariables(Object source, Map<String, Object> variables) {
        super.changeVariables(source, variables);
        if (variables.containsKey("value")) {
            final Object value = variables.get("value");
            final Double newValue = (Double) value;
            if (newValue != null && newValue != getValue() && !newValue.equals(getValue())) {
                try {
                    setInternalVal(newValue, true);
                } catch (final ValueOutOfBoundsException e) {
                    // Convert to nearest bound
                    double out = e.getValue().doubleValue();
                    if (out < min.doubleValue()) {
                        out = min.doubleValue();
                    }
                    if (out > max.doubleValue()) {
                        out = max.doubleValue();
                    }
                    super.setValue(new Double(out), false);
                }
            }
        }
    }

    @SuppressWarnings("unchecked")
    protected void fireValueChangeListeners() {
        for (SliderValueListener<T> list : listeners) {
            Object value = super.getValue();
            list.sliderValuesChanged((T) SliderUtil.getValue(_numberClass, (Number) value));
        }
    }

    /**
     * Gets the biggest possible value in Sliders range.
     * 
     * @return the biggest value slider can have
     */
    public T getMax() {
        return max;
    }

    /**
     * Gets the minimum value in Sliders range.
     * 
     * @return the smalles value slider can have
     */
    public T getMin() {
        return min;
    }

    public int getNumberLabels() {
        return numLabels;
    }

    public int getNumberTicks() {
        return numTicks;
    }

    /**
     * Get the current stepSize of the Slider.
     * 
     * @return stepSize
     */
    public T getStepSize() {
        return stepSize;
    }

    @Override
    public Class<?> getType() {
        return _numberClass;
    }

    public boolean isSuperImmediateMode() {
        return superImmediateMode;
    }

    @Override
    public void paintContent(PaintTarget target) throws PaintException {
        super.paintContent(target);
        target.addAttribute("min", min.doubleValue());
        if (max.doubleValue() > min.doubleValue()) {
            target.addAttribute("max", max.doubleValue());
        } else {
            target.addAttribute("max", min.doubleValue());
        }
        target.addAttribute("stepsize", stepSize.doubleValue());
        target.addAttribute("numticks", numTicks);
        target.addAttribute("numlabels", numLabels);
        target.addAttribute("superimmediate", superImmediateMode);
        if (_dateLabelFormat != null) {
            target.addAttribute("dateformat", _dateLabelFormat.name());
        }
        if (stepSize.doubleValue() > 0) {
            target.addVariable(this, "value", ((Number) getValue()).doubleValue());
        } else {
            target.addVariable(this, "value", ((Number) getValue()).intValue());
        }
    }

    public void removeRangeValueListener(SliderValueListener<T> listener) {
        if (listeners.contains(listener)) {
            listeners.remove(listener);
        }
    }

    /**
     * Set the value of this Slider.
     * 
     * @param value
     *            New value of Slider. Must be within Sliders range (min - max),
     *            otherwise throws an exception.
     * @param repaintIsNotNeeded
     *            If true, client-side is not requested to repaint itself.
     * @throws ValueOutOfBoundsException
     */
    private void setInternalVal(Double value, boolean repaintIsNotNeeded) throws ValueOutOfBoundsException {
        double newValue = value.doubleValue();

        super.setValue(new Double(newValue), repaintIsNotNeeded);
        if (repaintIsNotNeeded) {
            fireValueChangeListeners();

        }
    }

    private void setInternalVal(Number value) {
        try {
            setInternalVal(value.doubleValue(), false);
        } catch (ValueOutOfBoundsException todo) {
            todo.printStackTrace();
        }

    }

    /**
     * Set the maximum value of the Slider. If the current value of the Slider
     * is out of new bounds, the value is set to new minimum.
     * 
     * @param max
     *            New maximum value of the Slider.
     */
    public void setMax(T max) {
        this.max = max;
        try {
            if ((new Double(getValue().toString())).doubleValue() > max.doubleValue()) {
                setInternalVal(new Double(max.doubleValue()));
            }
        } catch (final ClassCastException e) {
            // FIXME: Handle exception
            /*
             * Where does ClassCastException come from? Can't see any casts
             * above
             */
            setInternalVal(new Double(max.doubleValue()));
        }
        requestRepaint();
    }

    /**
     * Set the minimum value of the Slider. If the current value of the Slider
     * is out of new bounds, the value is set to new minimum.
     * 
     * @param min
     *            New minimum value of the Slider.
     */
    public void setMin(T min) {
        this.min = min;
        try {
            if ((new Double(getValue().toString())).doubleValue() < min.doubleValue()) {
                super.setValue(new Double(min.doubleValue()));
            }
        } catch (final ClassCastException e) {
            // FIXME: Handle exception
            /*
             * Where does ClassCastException come from? Can't see any casts
             * above
             */
            super.setValue(new Double(min.doubleValue()));
        }
        requestRepaint();
    }

    /**
     * The number of labels to show.
     */
    public void setNumberLabels(int numLabels) {
        this.numLabels = numLabels;
    }

    /**
     * The number of tick marks to show.
     */
    public void setNumberTicks(int numTicks) {
        this.numTicks = numTicks;
    }

    /**
     * This method is used instead of {@link #setValue(T)} without throwing
     * exception. The val is set to max or min if it exceeds the min or max
     * value accordingly
     * 
     * @param val
     *            .
     */
    public void setSliderValue(T val) {
        if (val.doubleValue() > max.doubleValue()) {
            setInternalVal(max);
        } else if (val.doubleValue() < min.doubleValue()) {
            setInternalVal(min);
            return;
        } else
            setInternalVal(val);
    }

    /**
     * Set a new stepSize for the Slider.
     * 
     * @param stepSize
     */
    public void setStepSize(T stepSize) {
        if (stepSize.doubleValue() < 0) {
            return;
        }
        this.stepSize = stepSize;
        requestRepaint();
    }

    /**
     * If super immediate mode is true, values are immediately received from
     * client when dragging with the mouse and when the Arrow keys are pressed
     * down
     * 
     * @param superImmediateMode
     */

    public void setSuperImmediateMode(boolean superImmediateMode) {
        if (superImmediateMode)
            this.setImmediate(true);
        this.superImmediateMode = superImmediateMode;
        requestRepaint();
    }

    /**
     * Set the value of this Slider.
     * 
     * @param value
     *            New value of Slider. Must be within Sliders range (min - max),
     *            otherwise throws an exception.
     * @throws ValueOutOfBoundsException
     */
    @SuppressWarnings("unchecked")
    @Override
    public void setValue(Object value) {
        if (value.getClass() != _numberClass) {
            throw new IllegalArgumentException(
                    String.format("Class mismatch. Value is of class %s while value of class %s was expected",
                            value.getClass().getName(), _numberClass.getName()));

        }
        try {
            this.setValue((T) value);
        } catch (ValueOutOfBoundsException e) {
            throw new RuntimeException(e);
        }

    }

    public void setValue(T value) throws ValueOutOfBoundsException {

        setValue(new Double(value.doubleValue()), false);

    }

    public DateLabelFormat getDateLabelFormat() {
        return _dateLabelFormat;
    }

    public void setLabelAsDate(DateLabelFormat _dateLabelFormat) {
        this._dateLabelFormat = _dateLabelFormat;
    }

}