package org.ege.widget;
import org.ege.utils.E;
import org.ege.widget.callback.OnValueListener;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.graphics.g2d.TextureRegion;
import com.badlogic.gdx.scenes.scene2d.Actor;
import com.badlogic.gdx.scenes.scene2d.InputEvent;
import com.badlogic.gdx.scenes.scene2d.InputListener;
public class Slider extends Actor {
SliderStyle mStyle;
int mOrientaion;
OnValueListener mValueListener;
private float rotation;
// ----------------------------------------------
public float min;
public float max;
public float step;
private float value;
// ----------------------------------------------
private final float mKnobSizePercent;
private final float mKnobWHRatio;
private float mKnobX;
private float mKnobY;
private float mKnobWidth;
private float mKnobHeight;
private final float mDelta;
private float mCurrentValuePercent;
// ----------------------------------------------
private TextureRegion tmp;
private int regionWidth;
private float mProcessWidth;
private float mProcessHeight;
private final int mFirstWidth;
private final int mFirstHeight;
public float mFrameDuration;
private float mStateTime = 0;
private int mKeyFrame = 0;
// ----------------------------------------------
boolean isFocusing = false;
boolean isAnimating = false;
public Slider(SliderStyle style){
super();
mStyle = style;
setBounds(0, 0, 100, 13);
setRotation(mOrientaion == E.orientation.LANDSCAPE ? 0 : 90);
/* ----------------------------- */
min = style.min;
max = style.max;
step = style.step;
value = style.value;
mDelta = max - min;
mCurrentValuePercent = value / mDelta;
/* ----------------------------- */
mKnobSizePercent = style.knobsize;
mKnobWHRatio = (float)mStyle.knob.getRegionWidth() /
(float)mStyle.knob.getRegionHeight();
mKnobHeight = getHeight() * mKnobSizePercent;
mKnobWidth = mKnobWHRatio*mKnobHeight;
/* ----------------------------- */
if(mStyle.process != null){
mFirstWidth = mStyle.process[0].getRegionWidth();
mFirstHeight = mStyle.process[0].getRegionHeight();
}else{
mFirstWidth = 0;
mFirstHeight = 0;
}
if(mOrientaion == E.orientation.LANDSCAPE){
mKnobX = (mCurrentValuePercent*(getWidth() - mKnobWidth))+ getX();
mKnobY = getY() + getHeight()/2 - mKnobHeight/2;
mProcessWidth = mKnobX + mKnobWidth/2 - getX();
mProcessHeight = getHeight();
}else{
mKnobX = getX() + getHeight()/2 - mKnobHeight/2;
mKnobY = (mCurrentValuePercent*(getWidth() - mKnobWidth))+ getY();
mProcessWidth = mKnobY + mKnobWidth/2 - getY();
mProcessHeight = getHeight();
}
addListener(new SliderController());
}
/*****************************************************
*
*****************************************************/
public void setRegion(TextureRegion background,TextureRegion knob,TextureRegion...process){
mStyle.background = background;
mStyle.knob = knob;
mStyle.process = process;
}
public void setValueListner(OnValueListener listener){
mValueListener = listener;
}
public float getValue(){
return (float)Math.floor(value / step) * step;
}
/*****************************************************
*
*****************************************************/
private void calculatePositionAndValue(float x){
final float width = getWidth();
final float height = getHeight();
if(x < 0)
value = min;
else if (x > width)
value = max;
else
value = x/width*mDelta;
mCurrentValuePercent = value/mDelta;
mKnobHeight = height * mKnobSizePercent;
mKnobWidth = mKnobWHRatio*mKnobHeight;
if(mOrientaion == E.orientation.LANDSCAPE){
mKnobX = (mCurrentValuePercent*(width - mKnobWidth))+ getX();
mKnobY = getY() + height/2 - mKnobHeight/2;
mProcessWidth = mKnobX + mKnobWidth/2 - getX();
mProcessHeight = height;
}else{
mKnobX = getX() + height/2 - mKnobHeight/2;
mKnobY = (mCurrentValuePercent*(width - mKnobWidth))+ getY();
mProcessWidth = mKnobY + mKnobWidth/2 - getY();
mProcessHeight = height;
}
}
public void startAnimation(float FrameDuration){
mFrameDuration = FrameDuration;
isAnimating = true;
}
public void disableAnimation(){
isAnimating = false;
mStateTime = 0;
mKeyFrame = 0;
}
/*****************************************************
*
*****************************************************/
public void setValue(float value){
calculatePositionAndValue(value/mDelta*getWidth());
}
public void setMax(float max){
this.max= max;
}
public void setMin(float min){
this.min= min;
}
public void setStep(float step){
this.step= step;
}
/*****************************************************
*
*****************************************************/
@Override
public void draw (SpriteBatch batch, float parentAlpha) {
final Color color = getColor();
final float x = getX();
final float y = getY();
final float width = getWidth();
final float height = getHeight();
batch.setColor(color.r, color.g, color.b, color.a* parentAlpha);
if(mOrientaion == E.orientation.LANDSCAPE){
rotation = 0;
mKnobX = (mCurrentValuePercent*(width - mKnobWidth))+ x;
mKnobY = y + height/2 - mKnobHeight/2;
}else{
rotation = 90;
mKnobX = x + height/2 - mKnobHeight/2;
mKnobY = (mCurrentValuePercent*(width - mKnobWidth))+ y;
}
if(getScaleX() == 1 && getScaleY() == 1 && rotation == 0){
batch.draw(mStyle.background,x,y,width,height);
tmp = mStyle.process[mKeyFrame];
regionWidth = (int)(mCurrentValuePercent*mFirstWidth);
if(regionWidth < mFirstWidth - mKnobWidth)
tmp.setRegion((int)tmp.getRegionX(), (int)tmp.getRegionY(),
(int)(mCurrentValuePercent*mFirstWidth)+ (int)(mKnobWidth/2), (int)mFirstHeight);
else
tmp.setRegion((int)tmp.getRegionX(), (int)tmp.getRegionY(),
(int)(mCurrentValuePercent*mFirstWidth)+ (int)(mKnobWidth/4), (int)mFirstHeight);
batch.draw(tmp,x,y,mProcessWidth,mProcessHeight);
batch.draw(mStyle.knob,mKnobX,mKnobY,mKnobWidth,mKnobHeight);
tmp.setRegion(tmp.getRegionX(), tmp.getRegionY(), mFirstWidth, mFirstHeight);
}else{
batch.draw(mStyle.background,x,y,getOriginX(),getOriginY(),width,height,getScaleX(),getScaleY(),90);
tmp = mStyle.process[mKeyFrame];
regionWidth = (int)(mCurrentValuePercent*mFirstWidth);
if(regionWidth < mFirstWidth - mKnobWidth)
tmp.setRegion((int)tmp.getRegionX(), (int)tmp.getRegionY(),
(int)(mCurrentValuePercent*mFirstWidth)+ (int)(mKnobWidth/2), (int)mFirstHeight);
else
tmp.setRegion((int)tmp.getRegionX(), (int)tmp.getRegionY(),
(int)(mCurrentValuePercent*mFirstWidth)+ (int)(mKnobWidth/4), (int)mFirstHeight);
batch.draw(tmp,x,y,getOriginX(),getOriginY(),mProcessWidth,mProcessHeight,getScaleX(),getScaleY(),90);
batch.draw(mStyle.knob,mKnobX,mKnobY,getOriginX(),getOriginY(),mKnobWidth,mKnobHeight,getScaleX(),getScaleY(),90);
tmp.setRegion(tmp.getRegionX(), tmp.getRegionY(), mFirstWidth, mFirstHeight);
}
}
@Override
public void act (float delta) {
super.act(delta);
if(isAnimating){
mStateTime += delta;
if(mFrameDuration > 0){
mKeyFrame = (int) (mStateTime/mFrameDuration);
mKeyFrame = mKeyFrame % mStyle.process.length;
}else
mKeyFrame = 0;
}
}
/*****************************************************
*
*****************************************************/
class SliderController extends InputListener{
@Override
public boolean touchDown (InputEvent event, float x, float y,
int pointer, int button) {
if(hit(x, y,true) != null){
isFocusing = true;
calculatePositionAndValue(x);
if(mValueListener != null)
mValueListener.ValueChanged(Slider.this, getValue());
return true;
}
return false;
}
@Override
public void touchUp (InputEvent event, float x, float y, int pointer,
int button) {
isFocusing = false;
}
@Override
public void touchDragged (InputEvent event, float x, float y,
int pointer) {
if(isFocusing){
calculatePositionAndValue(x);
if(mValueListener != null)
mValueListener.ValueChanged(Slider.this, getValue());
}
}
@Override
public boolean mouseMoved (InputEvent event, float x, float y) {
return super.mouseMoved(event, x, y);
}
}
public void dispose(){
mStyle = null;
mValueListener = null;
}
public String info(){
if(mStyle.process == null)
return "min: " + min + " max: " + max + " step: " +step
+ " value: "+value + " mCurrentValuePercent: " + mCurrentValuePercent
+ " mDelta " + mDelta + " mProcessWidth " + mProcessWidth + " mProcessHeight " + mProcessHeight;
else
return "min: " + min + " max: " + max + " step: " +step
+ " value: "+value + " mCurrentValuePercent: " + mCurrentValuePercent
+ " mDelta " + mDelta + " mProcessWidth " + mProcessWidth + " mProcessHeight " + mProcessHeight +
mStyle.process.length;
}
/*****************************************************
*
*****************************************************/
public static class SliderStyle{
public TextureRegion background;
public TextureRegion knob;
public TextureRegion process[];
public int orientation = E.orientation.LANDSCAPE;
public float min = 0;
public float max =100;
public float step = 1;
public float value = 50;
public float knobsize = 1f;
}
}