/* @ITMillApache2LicenseForJavaFiles@ */ package com.vaadin.ui; import java.util.Map; import com.vaadin.terminal.PaintException; import com.vaadin.terminal.PaintTarget; import com.vaadin.terminal.gwt.client.ui.VSlider; /** * A component for selecting a numerical value within a range. * * Example code: * class MyPlayer extends CustomComponent implements ValueChangeListener { * * Label volumeIndicator = new Label(); * Slider slider; * * public MyPlayer() { * VerticalLayout vl = new VerticalLayout(); * setCompositionRoot(vl); * slider = new Slider("Volume", 0, 100); * slider.setImmediate(true); * slider.setValue(new Double(50)); * vl.addComponent(slider); * vl.addComponent(volumeIndicator); * volumeIndicator.setValue("Current volume:" + 50.0); * slider.addListener(this); * * } * * public void setVolume(double d) { * volumeIndicator.setValue("Current volume: " + d); * } * * public void valueChange(ValueChangeEvent event) { * Double d = (Double) event.getProperty().getValue(); * setVolume(d.doubleValue()); * } * } * * * * @author IT Mill Ltd. */ @SuppressWarnings("serial") @ClientWidget(VSlider.class) public class Slider extends AbstractField { public static final int ORIENTATION_HORIZONTAL = 0; public static final int ORIENTATION_VERTICAL = 1; /** * Style constant representing a scrollbar styled slider. Use this with * {@link #addStyleName(String)}. Default styling usually represents a * common slider found e.g. in Adobe Photoshop. The client side * implementation dictates how different styles will look. */ @Deprecated public static final String STYLE_SCROLLBAR = "scrollbar"; /** Minimum value of slider */ private double min = 0; /** Maximum value of slider */ private double max = 100; /** * Resolution, how many digits are considered relevant after the decimal * point. Must be a non-negative value */ private int resolution = 0; /** * Slider orientation (horizontal/vertical), defaults . */ private int orientation = ORIENTATION_HORIZONTAL; /** * Slider size in pixels. In horizontal mode, if set to -1, allow 100% width * of container. In vertical mode, if set to -1, default height is * determined by the client-side implementation. * * @deprecated */ @Deprecated private int size = -1; /** * Handle (draggable control element) size in percents relative to base * size. Must be a value between 1-99. Other values are converted to nearest * bound. A negative value sets the width to auto (client-side * implementation calculates). * * @deprecated The size is dictated by the current theme. */ @Deprecated private int handleSize = -1; /** * Show arrows that can be pressed to slide the handle in some increments * (client-side implementation decides the increment, usually somewhere * between 5-10% of slide range). */ @Deprecated private final boolean arrows = false; /** * Default Slider constructor. Sets all values to defaults and the slide * handle at minimum value. * */ public Slider() { super(); super.setValue(new Double(min)); } /** * Create a new slider with the caption given as parameter. All slider * values set to defaults. * * @param caption * The caption for this Slider (e.g. "Volume"). */ public Slider(String caption) { this(); setCaption(caption); } /** * Create a new slider with given range and resolution * * @param min * @param max * @param resolution */ public Slider(double min, double max, int resolution) { this(); setMin(min); setMax(max); setResolution(resolution); } /** * Create a new slider with given range * * @param min * @param max */ public Slider(int min, int max) { this(); setMin(min); setMax(max); setResolution(0); } /** * Create a new slider with given caption and range * * @param caption * @param min * @param max */ public Slider(String caption, int min, int max) { this(min, max); setCaption(caption); } /** * Gets the biggest possible value in Sliders range. * * @return the biggest value slider can have */ public double getMax() { return max; } /** * 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(double max) { this.max = max; try { if ((new Double(getValue().toString())).doubleValue() > max) { super.setValue(new Double(max)); } } catch (final ClassCastException e) { // FIXME: Handle exception /* * Where does ClassCastException come from? Can't see any casts * above */ super.setValue(new Double(max)); } requestRepaint(); } /** * Gets the minimum value in Sliders range. * * @return the smalles value slider can have */ public double getMin() { return min; } /** * 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(double min) { this.min = min; try { if ((new Double(getValue().toString())).doubleValue() < min) { super.setValue(new Double(min)); } } catch (final ClassCastException e) { // FIXME: Handle exception /* * Where does ClassCastException come from? Can't see any casts * above */ super.setValue(new Double(min)); } requestRepaint(); } /** * Get the current orientation of the Slider (horizontal or vertical). * * @return orientation */ public int getOrientation() { return orientation; } /** * Set the orientation of the Slider. * * @param int new orientation */ public void setOrientation(int orientation) { this.orientation = orientation; requestRepaint(); } /** * Get the current resolution of the Slider. * * @return resolution */ public int getResolution() { return resolution; } /** * Set a new resolution for the Slider. * * @param resolution */ public void setResolution(int resolution) { if (resolution < 0) { return; } this.resolution = resolution; requestRepaint(); } /** * 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 */ public void setValue(Double value, boolean repaintIsNotNeeded) throws ValueOutOfBoundsException { final double v = value.doubleValue(); double newValue; if (resolution > 0) { // Round up to resolution newValue = (int) (v * Math.pow(10, resolution)); newValue = newValue / Math.pow(10, resolution); if (min > newValue || max < newValue) { throw new ValueOutOfBoundsException(value); } } else { newValue = (int) v; if (min > newValue || max < newValue) { throw new ValueOutOfBoundsException(value); } } super.setValue(new Double(newValue), repaintIsNotNeeded); } /** * 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 */ public void setValue(Double value) throws ValueOutOfBoundsException { setValue(value, false); } /** * 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 */ public void setValue(double value) throws ValueOutOfBoundsException { setValue(new Double(value), false); } /** * Get the current Slider size. * * @return size in pixels or -1 for auto sizing. * @deprecated use standard getWidth/getHeight instead */ @Deprecated public int getSize() { return size; } /** * Set the size for this Slider. * * @param size * in pixels, or -1 auto sizing. * @deprecated use standard setWidth/setHeight instead */ @Deprecated public void setSize(int size) { this.size = size; switch (orientation) { case ORIENTATION_HORIZONTAL: setWidth(size, UNITS_PIXELS); break; default: setHeight(size, UNITS_PIXELS); break; } requestRepaint(); } /** * Get the handle size of this Slider. * * @return handle size in percentages. * @deprecated The size is dictated by the current theme. */ @Deprecated public int getHandleSize() { return handleSize; } /** * Set the handle size of this Slider. * * @param handleSize * in percentages relative to slider base size. * @deprecated The size is dictated by the current theme. */ @Deprecated public void setHandleSize(int handleSize) { if (handleSize < 0) { this.handleSize = -1; } else if (handleSize > 99) { this.handleSize = 99; } else if (handleSize < 1) { this.handleSize = 1; } else { this.handleSize = handleSize; } requestRepaint(); } @Override public void paintContent(PaintTarget target) throws PaintException { super.paintContent(target); target.addAttribute("min", min); if (max > min) { target.addAttribute("max", max); } else { target.addAttribute("max", min); } target.addAttribute("resolution", resolution); if (resolution > 0) { target.addVariable(this, "value", ((Double) getValue()).doubleValue()); } else { target.addVariable(this, "value", ((Double) getValue()).intValue()); } if (orientation == ORIENTATION_VERTICAL) { target.addAttribute("vertical", true); } if (arrows) { target.addAttribute("arrows", true); } if (size > -1) { target.addAttribute("size", size); } if (min != max && min < max) { target.addAttribute("hsize", handleSize); } else { target.addAttribute("hsize", 100); } } /** * Invoked when the value of a variable has changed. Slider listeners are * notified if the slider value has changed. * * @param source * @param variables */ @Override public void changeVariables(Object source, Map variables) { super.changeVariables(source, variables); if (variables.containsKey("value")) { final Object value = variables.get("value"); final Double newValue = new Double(value.toString()); if (newValue != null && newValue != getValue() && !newValue.equals(getValue())) { try { setValue(newValue, true); } catch (final ValueOutOfBoundsException e) { // Convert to nearest bound double out = e.getValue().doubleValue(); if (out < min) { out = min; } if (out > max) { out = max; } super.setValue(new Double(out), false); } } } } /** * ValueOutOfBoundsException * * @author IT Mill Ltd. * */ public class ValueOutOfBoundsException extends Exception { private final Double value; /** * Constructs an ValueOutOfBoundsException with the * specified detail message. * * @param valueOutOfBounds */ public ValueOutOfBoundsException(Double valueOutOfBounds) { value = valueOutOfBounds; } public Double getValue() { return value; } } @Override public Class getType() { return Double.class; } }