Package com.badlogic.gdx.scenes.scene2d.ui

Source Code of com.badlogic.gdx.scenes.scene2d.ui.Slider$SliderStyle

/*******************************************************************************
* Copyright 2011 See AUTHORS file.
*
* 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.
******************************************************************************/

package com.badlogic.gdx.scenes.scene2d.ui;

import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.g2d.NinePatch;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.graphics.g2d.TextureRegion;
import com.badlogic.gdx.math.Interpolation;
import com.badlogic.gdx.math.MathUtils;
import com.badlogic.gdx.scenes.scene2d.InputEvent;
import com.badlogic.gdx.scenes.scene2d.InputListener;
import com.badlogic.gdx.scenes.scene2d.utils.ChangeListener.ChangeEvent;
import com.badlogic.gdx.scenes.scene2d.utils.Disableable;
import com.badlogic.gdx.scenes.scene2d.utils.Drawable;
import com.badlogic.gdx.utils.Pools;

/** A slider is a horizontal indicator that allows a user to set a value. The slider has a range (min, max) and a stepping between
* each value the slider represents.
* <p>
* {@link ChangeEvent} is fired when the slider knob is moved. Cancelling the event will move the knob to where it was previously.
* <p>
* The preferred height of a slider is determined by the larger of the knob and background. The preferred width of a slider is
* 140, a relatively arbitrary size.
* @author mzechner
* @author Nathan Sweet */
public class Slider extends Widget implements Disableable {
  private SliderStyle style;
  private float min, max, stepSize;
  private float value, animateFromValue;
  private float sliderPos;
  private final boolean vertical;
  int draggingPointer = -1;
  private float animateDuration, animateTime;
  private Interpolation animateInterpolation = Interpolation.linear;
  private float[] snapValues;
  private float threshold;
  boolean disabled;

  public Slider (float min, float max, float stepSize, boolean vertical, Skin skin) {
    this(min, max, stepSize, vertical, skin.get("default-" + (vertical ? "vertical" : "horizontal"), SliderStyle.class));
  }

  public Slider (float min, float max, float stepSize, boolean vertical, Skin skin, String styleName) {
    this(min, max, stepSize, vertical, skin.get(styleName, SliderStyle.class));
  }

  /** Creates a new slider. It's width is determined by the given prefWidth parameter, its height is determined by the maximum of
   * the height of either the slider {@link NinePatch} or slider handle {@link TextureRegion}. The min and max values determine
   * the range the values of this slider can take on, the stepSize parameter specifies the distance between individual values.
   * E.g. min could be 4, max could be 10 and stepSize could be 0.2, giving you a total of 30 values, 4.0 4.2, 4.4 and so on.
   * @param min the minimum value
   * @param max the maximum value
   * @param stepSize the step size between values
   * @param style the {@link SliderStyle} */
  public Slider (float min, float max, float stepSize, boolean vertical, SliderStyle style) {
    if (min > max) throw new IllegalArgumentException("min must be > max: " + min + " > " + max);
    if (stepSize <= 0) throw new IllegalArgumentException("stepSize must be > 0: " + stepSize);
    setStyle(style);
    this.min = min;
    this.max = max;
    this.stepSize = stepSize;
    this.vertical = vertical;
    this.value = min;
    setWidth(getPrefWidth());
    setHeight(getPrefHeight());

    addListener(new InputListener() {
      public boolean touchDown (InputEvent event, float x, float y, int pointer, int button) {
        if (disabled) return false;
        if (draggingPointer != -1) return false;
        draggingPointer = pointer;
        calculatePositionAndValue(x, y);
        return true;
      }

      public void touchUp (InputEvent event, float x, float y, int pointer, int button) {
        if (pointer != draggingPointer) return;
        draggingPointer = -1;
        if (!calculatePositionAndValue(x, y)) {
          // Fire an event on touchUp even if the value didn't change, so listeners can see when a drag ends via isDragging.
          ChangeEvent changeEvent = Pools.obtain(ChangeEvent.class);
          fire(changeEvent);
          Pools.free(changeEvent);
        }
      }

      public void touchDragged (InputEvent event, float x, float y, int pointer) {
        calculatePositionAndValue(x, y);
      }
    });
  }

  public void setStyle (SliderStyle style) {
    if (style == null) throw new IllegalArgumentException("style cannot be null.");
    this.style = style;
    invalidateHierarchy();
  }

  /** Returns the slider's style. Modifying the returned style may not have an effect until {@link #setStyle(SliderStyle)} is
   * called. */
  public SliderStyle getStyle () {
    return style;
  }

  public void act (float delta) {
    super.act(delta);
    animateTime -= delta;
  }

  @Override
  public void draw (SpriteBatch batch, float parentAlpha) {
    SliderStyle style = this.style;
    boolean disabled = this.disabled;
    final Drawable knob = (disabled && style.disabledKnob != null) ? style.disabledKnob : style.knob;
    final Drawable bg = (disabled && style.disabledBackground != null) ? style.disabledBackground : style.background;
    final Drawable knobBefore = (disabled && style.disabledKnobBefore != null) ? style.disabledKnobBefore : style.knobBefore;
    final Drawable knobAfter = (disabled && style.disabledKnobAfter != null) ? style.disabledKnobAfter : style.knobAfter;

    Color color = getColor();
    float x = getX();
    float y = getY();
    float width = getWidth();
    float height = getHeight();
    float knobHeight = knob == null ? 0 : knob.getMinHeight();
    float knobWidth = knob == null ? 0 : knob.getMinWidth();
    float value = getVisualValue();

    batch.setColor(color.r, color.g, color.b, color.a * parentAlpha);

    if (vertical) {
      bg.draw(batch, x + (int)((width - bg.getMinWidth()) * 0.5f), y, bg.getMinWidth(), height);

      float sliderPosHeight = height - (bg.getTopHeight() + bg.getBottomHeight());
      if (min != max) {
        sliderPos = (value - min) / (max - min) * (sliderPosHeight - knobHeight);
        sliderPos = Math.max(0, sliderPos);
        sliderPos = Math.min(sliderPosHeight - knobHeight, sliderPos) + bg.getBottomHeight();
      }

      float knobHeightHalf = knobHeight * 0.5f;
      if (knobBefore != null) {
        knobBefore.draw(batch, x + (int)((width - knobBefore.getMinWidth()) * 0.5f), y, knobBefore.getMinWidth(),
          (int)(sliderPos + knobHeightHalf));
      }
      if (knobAfter != null) {
        knobAfter.draw(batch, x + (int)((width - knobAfter.getMinWidth()) * 0.5f), y + (int)(sliderPos + knobHeightHalf),
          knobAfter.getMinWidth(), height - (int)(sliderPos + knobHeightHalf));
      }
      if (knob != null) knob.draw(batch, x + (int)((width - knobWidth) * 0.5f), (int)(y + sliderPos), knobWidth, knobHeight);
    } else {
      bg.draw(batch, x, y + (int)((height - bg.getMinHeight()) * 0.5f), width, bg.getMinHeight());

      float sliderPosWidth = width - (bg.getLeftWidth() + bg.getRightWidth());
      if (min != max) {
        sliderPos = (value - min) / (max - min) * (sliderPosWidth - knobWidth);
        sliderPos = Math.max(0, sliderPos);
        sliderPos = Math.min(sliderPosWidth - knobWidth, sliderPos) + bg.getLeftWidth();
      }

      float knobHeightHalf = knobHeight * 0.5f;
      if (knobBefore != null) {
        knobBefore.draw(batch, x, y + (int)((height - knobBefore.getMinHeight()) * 0.5f), (int)(sliderPos + knobHeightHalf),
          knobBefore.getMinHeight());
      }
      if (knobAfter != null) {
        knobAfter.draw(batch, x + (int)(sliderPos + knobHeightHalf), y + (int)((height - knobAfter.getMinHeight()) * 0.5f),
          width - (int)(sliderPos + knobHeightHalf), knobAfter.getMinHeight());
      }
      if (knob != null)
        knob.draw(batch, (int)(x + sliderPos), (int)(y + (height - knobHeight) * 0.5f), knobWidth, knobHeight);
    }
  }

  boolean calculatePositionAndValue (float x, float y) {
    final Drawable knob = (disabled && style.disabledKnob != null) ? style.disabledKnob : style.knob;
    final Drawable bg = (disabled && style.disabledBackground != null) ? style.disabledBackground : style.background;

    float value;
    float oldPosition = sliderPos;

    if (vertical) {
      float height = getHeight() - bg.getTopHeight() - bg.getBottomHeight();
      float knobHeight = knob == null ? 0 : knob.getMinHeight();
      sliderPos = y - bg.getBottomHeight() - knobHeight * 0.5f;
      value = min + (max - min) * (sliderPos / (height - knobHeight));
      sliderPos = Math.max(0, sliderPos);
      sliderPos = Math.min(height - knobHeight, sliderPos);
    } else {
      float width = getWidth() - bg.getLeftWidth() - bg.getRightWidth();
      float knobWidth = knob == null ? 0 : knob.getMinWidth();
      sliderPos = x - bg.getLeftWidth() - knobWidth * 0.5f;
      value = min + (max - min) * (sliderPos / (width - knobWidth));
      sliderPos = Math.max(0, sliderPos);
      sliderPos = Math.min(width - knobWidth, sliderPos);
    }

    float oldValue = value;
    boolean valueSet = setValue(value);
    if (value == oldValue) sliderPos = oldPosition;
    return valueSet;
  }

  /** Returns true if the slider is being dragged. */
  public boolean isDragging () {
    return draggingPointer != -1;
  }

  public float getValue () {
    return value;
  }

  /** If {@link #setAnimateDuration(float) animating} the slider value, this returns the value current displayed. */
  public float getVisualValue () {
    if (animateTime > 0) return animateInterpolation.apply(animateFromValue, value, 1 - animateTime / animateDuration);
    return value;
  }

  /** Sets the slider position, rounded to the nearest step size and clamped to the minumum and maximim values.
   * {@link #clamp(float)} can be overidden to allow values outside of the sliders min/max range.
   * @return false if the value was not changed because the slider already had the value or it was canceled by a listener. */
  public boolean setValue (float value) {
    value = snap(clamp(Math.round(value / stepSize) * stepSize));
    float oldValue = this.value;
    if (value == oldValue) return false;
    float oldVisualValue = getVisualValue();
    this.value = value;
    ChangeEvent changeEvent = Pools.obtain(ChangeEvent.class);
    boolean cancelled = fire(changeEvent);
    if (cancelled)
      this.value = oldValue;
    else if (animateDuration > 0) {
      animateFromValue = oldVisualValue;
      animateTime = animateDuration;
    }
    Pools.free(changeEvent);
    return !cancelled;
  }

  /** Clamps the value to the sliders min/max range. This can be overidden to allow a range different from the slider knob's
   * range. */
  protected float clamp (float value) {
    return MathUtils.clamp(value, min, max);
  }

  /** Sets the range of this slider. The slider's current value is reset to min. */
  public void setRange (float min, float max) {
    if (min > max) throw new IllegalArgumentException("min must be <= max");
    this.min = min;
    this.max = max;
    if (value < min)
      setValue(min);
    else if (value > max) setValue(max);
  }

  /** Sets the step size of the slider */
  public void setStepSize (float stepSize) {
    if (stepSize <= 0) throw new IllegalArgumentException("steps must be > 0: " + stepSize);
    this.stepSize = stepSize;
  }

  public float getPrefWidth () {
    if (vertical) {
      final Drawable knob = (disabled && style.disabledKnob != null) ? style.disabledKnob : style.knob;
      final Drawable bg = (disabled && style.disabledBackground != null) ? style.disabledBackground : style.background;
      return Math.max(knob == null ? 0 : knob.getMinWidth(), bg.getMinWidth());
    } else
      return 140;
  }

  public float getPrefHeight () {
    if (vertical)
      return 140;
    else {
      final Drawable knob = (disabled && style.disabledKnob != null) ? style.disabledKnob : style.knob;
      final Drawable bg = (disabled && style.disabledBackground != null) ? style.disabledBackground : style.background;
      return Math.max(knob == null ? 0 : knob.getMinHeight(), bg.getMinHeight());
    }
  }

  public float getMinValue () {
    return this.min;
  }

  public float getMaxValue () {
    return this.max;
  }

  public float getStepSize () {
    return this.stepSize;
  }

  /** If > 0, changes to the slider value via {@link #setValue(float)} will happen over this duration in seconds. */
  public void setAnimateDuration (float duration) {
    this.animateDuration = duration;
  }

  /** Sets the interpolation to use for {@link #setAnimateDuration(float)}. */
  public void setAnimateInterpolation (Interpolation animateInterpolation) {
    if (animateInterpolation == null) throw new IllegalArgumentException("animateInterpolation cannot be null.");
    this.animateInterpolation = animateInterpolation;
  }

  /** Will make this slider snap to the specified values, if the knob is within the threshold */
  public void setSnapToValues (float[] values, float threshold) {
    this.snapValues = values;
    this.threshold = threshold;
  }

  /** Returns a snapped value, or the original value */
  private float snap (float value) {
    if (snapValues == null) return value;
    for (int i = 0; i < snapValues.length; i++) {
      if (Math.abs(value - snapValues[i]) <= threshold) return snapValues[i];
    }
    return value;
  }

  public void setDisabled (boolean disabled) {
    this.disabled = disabled;
  }

  public boolean isDisabled () {
    return disabled;
  }

  /** The style for a slider, see {@link Slider}.
   * @author mzechner
   * @author Nathan Sweet */
  static public class SliderStyle {
    /** The slider background, stretched only in one direction. */
    public Drawable background;
    /** Optional. **/
    public Drawable disabledBackground;
    /** Optional, centered on the background. */
    public Drawable knob, disabledKnob;
    /** Optional. */
    public Drawable knobBefore, knobAfter, disabledKnobBefore, disabledKnobAfter;

    public SliderStyle () {
    }

    public SliderStyle (Drawable background, Drawable knob) {
      this.background = background;
      this.knob = knob;
    }

    public SliderStyle (SliderStyle style) {
      this.background = style.background;
      this.knob = style.knob;
    }
  }
}
TOP

Related Classes of com.badlogic.gdx.scenes.scene2d.ui.Slider$SliderStyle

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.