////////////////////////////////////////////////////////////////////////////////
// GLSlider.cpp
// Copyright Björn Ganster 
// Developed since 2007
////////////////////////////////////////////////////////////////////////////////

#include "Config.h"
#include "GLSlider.h"

////////////////////////////////////////////////////////////////////////////////
// Constructor

GLSlider::GLSlider (GLWindow* _parent, int _left, int _top, int _width, int _height)
: GLWindow ("GLSlider", GLSlider_ID, _parent, _left, _top, _width, _height),
  dialColor (0, 0, 0),
  mMin (0),
  mMax (1),
  mLineColor(0.5),
  mSteps(0),
  mLeftButtonDown(false)
{
	Config* config = getConfig();
	mLineColor = config->getTextColor();
	mGaugeColor = Color(0, 1, 0);
}

////////////////////////////////////////////////////////////////////////////////
// Destructor

GLSlider::~GLSlider()
{
}

////////////////////////////////////////////////////////////////////////////////
// Events

void GLSlider::keypressed (BGKey /*key*/, bool /*shiftHeld*/, bool /*ctrlHeld*/, bool /*down*/, bool /*repeat*/)
{
}

////////////////////////////////////////////////////////////////////////////////
// Kleinscheiß

// Button state changed over a window: returns child that was clicked
GLWindow* GLSlider::buttonStateChanged (int button, bool down, int /*x*/, int /*y*/)
{
    if (button == 1)
        mLeftButtonDown = down;
    return this; 
}

// Get/Set minimum, maximum value
void GLSlider::setMinMax (double newMin, double newMax)
{
	mMin = newMin;
	mMax = newMax;
}

double GLSlider::getMin () const
{
	return mMin;
}

double GLSlider::getMax () const
{
	return mMax;
}

// Get/Set value
bool GLSlider::setValue (double newVal)
{
    if (newVal >= mMin && newVal <= mMax) {
        mCurrValue = newVal;
        return true;
    } else
        return false;
}

double GLSlider::getValue() const
{
    return mCurrValue;
}

// Get/set number of steps, zero steps: continuous values
void GLSlider::setDialCount(int newCount)
{
	mSteps = newCount;
}

int GLSlider::getDialCount()
{
	return mSteps;
}

////////////////////////////////////////////////////////////////////////////////
// Render

void GLSlider::render(int x, int y, int w, int h)
{
   glMatrixMode (GL_PROJECTION);
   glLoadIdentity ();
   glMatrixMode (GL_MODELVIEW);
   glLoadIdentity ();

   setViewport (x, y, w, h);
   glDisable (GL_TEXTURE_2D);
   glDisable (GL_DEPTH_TEST);

   glLoadIdentity();
   glTranslated (-1.0, 1.0, 0.0);
   glScaled (2/((double) getWidth()), -2/((double) getHeight()), 1.0);

   // Render lines
   mLineColor.glColor();
   int y1 = height/3;
   int y2 = 2*height/3;
   glBegin (GL_LINES);
	   if (mSteps > 1) {
		  for (int i = 0; i < mSteps; i++) {
			 int x = i*(width-1)/(mSteps-1)+1;
			 glVertex2d (x, y1);
			 glVertex2d (x, y2);
		  }
	   } else {
		  for (int i = 0; i <= 10; i++) {
			 int x = i*(width-1)/10;
			 glVertex2d (x, y1);
			 glVertex2d (x, y2);
		  }
	   }

	   /*x = (curr-min)*(double)width/(double)(max-min);
	   glColor3f (1.0, 0.0, 0.0);
	   glVertex2d (x, y1);
	   glVertex2d (x, y2);*/
   glEnd();

   // Render top hand
   const int triSize = height/3;
   x = (int) ((mCurrValue-mMin)*(double)(width-1)/(double)(mMax-mMin));
   mGaugeColor.glColor();
   glBegin (GL_TRIANGLES);
      glVertex2d (x-triSize, 0);
      glVertex2d (x+triSize, 0);
      glVertex2d (x, triSize);
   glEnd();

   // Render bottom hand
   //triangleColor.glColor();
   glBegin (GL_TRIANGLES);
      glVertex2d (x-triSize, height);
      glVertex2d (x+triSize, height);
      glVertex2d (x, 2*triSize);
   glEnd();
}

void GLSlider::mouseMoved (int x, int /*y*/)
{
	if (!mLeftButtonDown)
		return;

	if (mSteps == 0) {
		mCurrValue = mMin + (x-left)*(mMax-mMin)/width;
	} else {
		int newStep = (mSteps-1) * (x-left)/width;
		mCurrValue = mMin + newStep * mMax / (mSteps-1);
	}

	if (mCurrValue < mMin)
		mCurrValue = mMin;
	else if (mCurrValue > mMax)
		mCurrValue = mMax;
	sendMessage (listener, ValueChangedEvent);
}
