// (C) 2005 Max Howell (max.howell@methylblue.com)
// See COPYING file for licensing information

#include <twin.h>
#include <tqlabel.h>
#include <tqlayout.h>
#include <tqslider.h>

#include "../mxcl.library.h"
#include "videoSettings.h"
#include "xineEngine.h"


extern "C"
{
   // #include <X11/Xlib.h> is just dangerous! Here, there is a macro for Below that conflicts
   // with TQSlider::Below. Stupid X11 people.
   typedef unsigned long XID;
   typedef XID Window;
   extern int XSetTransientForHint( Display*, Window, Window );
}


//TODO update from engine when new video is played
//TODO show a warning that when paused the changes aren't updated to the display, show an unpause button too


class SnapSlider : public TQSlider
{
   int m_offset;

public:
   SnapSlider( const int value, TQWidget *parent, const char *name )
         : TQSlider( (65536/4)-1, (3*(65536/4))-1, 1000, value, TQt::Horizontal, parent, name )
         , m_offset( 0 )
   {
      setTickmarks( TQSlider::Below );
      setTickInterval( 65536 / 4 );
      setMinimumWidth( fontMetrics().width( name ) * 3 );
      connect( this, SIGNAL(valueChanged( int )), Codeine::engine(), SLOT(setStreamParameter( int )) );
   }

   virtual void mousePressEvent( TQMouseEvent *e )
   {
      m_offset = e->pos().x() - (sliderStart() + (sliderRect().width()/2));
      TQSlider::mousePressEvent( e );
   }

   virtual void mouseMoveEvent( TQMouseEvent *e )
   {
      const int MIDDLE = width() / 2;
      const int x = e->pos().x() - m_offset;
      const int F = sliderRect().width() / 2;

      if( x > MIDDLE - F && x < MIDDLE + F ) {
         TQMouseEvent e2( e->type(), TQPoint( MIDDLE + m_offset, e->pos().y() ), e->button(), e->state() );
         TQSlider::mouseMoveEvent( &e2 );
         TQRangeControl::setValue( 65536 / 2 - 1 ); // to ensure we are absolutely exact
      }
      else
         TQSlider::mouseMoveEvent( e );
   }
};


Codeine::VideoSettingsDialog::VideoSettingsDialog( TQWidget *parent )
      : KDialog( parent, "video_settings_dialog", false, WType_TopLevel | WDestructiveClose )
{
   XSetTransientForHint( x11Display(), winId(), parent->winId() );
   KWin::setType( winId(), NET::Utility );
   KWin::setState( winId(), NET::SkipTaskbar );

   TQFrame *frame = new TQFrame( this );
   (new TQVBoxLayout( this, 10 ))->addWidget( frame );
   frame->setFrameStyle( TQFrame::StyledPanel | TQFrame::Sunken );
   frame->setPaletteBackgroundColor( backgroundColor().dark( 102 ) );

   TQGridLayout *grid = new TQGridLayout( frame, 4, 2, 15, 10 );
   grid->setAutoAdd( true );

   #define makeSlider( PARAM, name ) \
            new TQLabel( name, frame ); \
            new SnapSlider( xine_get_param( *Codeine::engine(), PARAM ), frame, name );

   makeSlider( XINE_PARAM_VO_BRIGHTNESS, "brightness" );
   makeSlider( XINE_PARAM_VO_CONTRAST, "contrast" );
   makeSlider( XINE_PARAM_VO_SATURATION, "saturation" );
   makeSlider( XINE_PARAM_VO_HUE, "hue" );

   #undef makeSlider

   setCaption( i18n("Video Settings") );
   setMaximumSize( sizeHint().width() * 5, sizeHint().height() );

   KDialog::show();
}

void
Codeine::VideoSettingsDialog::stateChanged( TQWidget *parent, Engine::State state ) //static
{
   TQWidget *me = (TQWidget*)parent->child( "video_settings_dialog" );

   if( !me )
      return;

   switch( state )
   {
   case Engine::Playing:
   case Engine::Paused:
      me->setEnabled( true );
      break;

   case Engine::Loaded:
      #define update( param, name ) static_cast<TQSlider*>(me->child( name ))->setValue( xine_get_param( *Codeine::engine(), param ) );
      update( XINE_PARAM_VO_BRIGHTNESS, "brightness" );
      update( XINE_PARAM_VO_CONTRAST, "contrast" );
      update( XINE_PARAM_VO_SATURATION, "saturation" );
      update( XINE_PARAM_VO_HUE, "hue" );
      #undef update

   default:
      me->setEnabled( false );
      break;
   }
}

namespace Codeine
{
   void showVideoSettingsDialog( TQWidget *parent )
   {
      // ensure that the dialog is shown by deleting the old one
      delete parent->child( "video_settings_dialog" );

      new VideoSettingsDialog( parent );
   }
}
