/***************************************************************************
                          kplayerslideraction.cpp
                          -----------------------
    begin                : Sat Jan 11 2003
    copyright            : (C) 2003-2007 by kiriuja
    email                : http://kplayer.sourceforge.net/email.html
 ***************************************************************************/

/***************************************************************************
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation, either version 3 of the License, or     *
 *   (at your option) any later version.                                   *
 ***************************************************************************/

#include <tdeapplication.h>
#include <tdetoolbar.h>
#include <tdetoolbarbutton.h>
#include <tqcursor.h>
#include <tqtooltip.h>
#include <tqwhatsthis.h>

#ifdef DEBUG
#define DEBUG_KPLAYER_SLIDERS
#define DEBUG_KPLAYER_SLIDER_HINTS
#endif

#include "kplayerslideraction.h"
#include "kplayerslideraction.moc"
#include "kplayerengine.h"
#include "kplayersettings.h"

KPlayerPopupFrame::~KPlayerPopupFrame()
{
#ifdef DEBUG_KPLAYER_SLIDERS
  kdDebugTime() << "KPlayerPopupFrame destroyed\n";
#endif
}

void KPlayerPopupFrame::keyPressEvent (TQKeyEvent* ev)
{
  switch ( ev -> key() )
  {
    case Key_Alt:
    case Key_Tab:
    case Key_Escape:
    case Key_Return:
    case Key_Enter:
      close();
  }
}

KPlayerPopupSliderAction::KPlayerPopupSliderAction (const TQString& text,
    const TQString& pix, const TDEShortcut& shortcut, const TQObject* receiver,
    const char* slot, TQObject* parent, const char* name)
  : TDEAction (text, pix, shortcut, parent, name)
{
  m_frame = new KPlayerPopupFrame;
  m_frame -> setFrameStyle (TQFrame::PopupPanel | TQFrame::Raised);
  m_frame -> setLineWidth (2);
  m_slider = new KPlayerSlider (TQt::Vertical, m_frame);
  m_frame -> resize (36, m_slider -> sizeHint().height() + 4);
  m_slider -> setGeometry (m_frame -> contentsRect());
#ifdef DEBUG_KPLAYER_SLIDERS
  kdDebugTime() << "Popup slider size " << m_slider -> width() << "x" << m_slider -> height() << "\n";
#endif
  connect (m_slider, TQ_SIGNAL (changed (int)), receiver, slot);
  if ( ! text.isEmpty() )
    TQToolTip::add (m_slider, text);
}

KPlayerPopupSliderAction::~KPlayerPopupSliderAction()
{
#ifdef DEBUG_KPLAYER_SLIDERS
  kdDebugTime() << "KPlayerPopupSliderAction destroyed\n";
#endif
}

void KPlayerPopupSliderAction::slotActivated (void)
{
  TDEAction::slotActivated();
  TQWidget* button = 0;
#ifdef DEBUG_KPLAYER_SLIDERS
  if ( sender() )
    kdDebugTime() << "Sender class name: " << sender() -> className() << "\n";
#endif
  if ( sender() && sender() -> inherits ("TDEToolBarButton") )
    button = (TQWidget*) sender();
  else
  {
    TDEToolBar* toolbar = 0;
    int index;
    if ( sender() -> inherits ("TDEToolBar") )
      toolbar = (TDEToolBar*) sender();
    else
      for ( index = 0; index < containerCount() && (! toolbar || ! toolbar -> isVisible()); index ++ )
	toolbar = toolBar (index);
    if ( toolbar && toolbar -> isVisible() )
    {
      int index = findContainer (toolbar);
      if ( index >= 0 )
        button = toolbar -> getButton (itemId (index));
    }
  }
  TQPoint point;
  if ( button )
  {
    point = button -> mapToGlobal (TQPoint (0, button -> height()));
    if ( point.y() + m_frame -> height() > TQApplication::desktop() -> height() )
      point.setY (point.y() - button -> height() - m_frame -> height());
  }
  else
  {
    point = TQCursor::pos() - TQPoint (m_frame -> width() / 2, m_frame -> height() / 2);
    if ( point.x() + m_frame -> width() > TQApplication::desktop() -> width() )
      point.setX (TQApplication::desktop() -> width() - m_frame -> width());
    if ( point.y() + m_frame -> height() > TQApplication::desktop() -> height() )
      point.setY (TQApplication::desktop() -> height() - m_frame -> height());
    if ( point.x() < 0 )
      point.setX (0);
    if ( point.y() < 0 )
      point.setY (0);
  }
#ifdef DEBUG_KPLAYER_SLIDERS
  kdDebugTime() << "Point: " << point.x() << "x" << point.y() << "\n";
#endif
  TQWhatsThis::add (m_frame, whatsThis());
  TQWhatsThis::add (m_slider, whatsThis());
  m_frame -> move (point);
  m_frame -> show();
  m_slider -> setFocus();
}

KPlayerSliderAction::KPlayerSliderAction (const TQString& text, const TDEShortcut& cut,
    const TQObject* receiver, const char* slot, TDEActionCollection* parent, const char* name)
  : KWidgetAction (new KPlayerSlider (TQt::Horizontal, 0, name), text, cut, 0, 0, parent, name)
{
  setAutoSized (true);
  setShortcutConfigurable (false);
  connect (slider(), TQ_SIGNAL (changed (int)), receiver, slot);
}

KPlayerSliderAction::~KPlayerSliderAction()
{
#ifdef DEBUG_KPLAYER_SLIDERS
  kdDebugTime() << "KPlayerSliderAction destroyed\n";
#endif
}

int KPlayerSliderAction::plug (TQWidget* widget, int index)
{
  int result = KWidgetAction::plug (widget, index);
  if ( result < 0 )
    return result;
  TDEToolBar* toolbar = (TDEToolBar*) widget;
  if ( ! text().isEmpty() )
    TQToolTip::add (slider(), text());
  orientationChanged (toolbar -> orientation());
  connect (toolbar, TQ_SIGNAL (orientationChanged (Orientation)), this, TQ_SLOT (orientationChanged (Orientation)));
  return result;
}

void KPlayerSliderAction::unplug (TQWidget* widget)
{
  KWidgetAction::unplug (widget);
  if ( ! slider() || ! isPlugged() || widget != slider() -> parent() )
    return;
  disconnect (widget, TQ_SIGNAL (orientationChanged (Orientation)), this, TQ_SLOT (orientationChanged (Orientation)));
}

void KPlayerSliderAction::orientationChanged (Orientation orientation)
{
  if ( slider() )
    slider() -> setOrientation (orientation);
}

KPlayerSlider::KPlayerSlider (TQt::Orientation orientation, TQWidget* parent, const char* name)
  : TQSlider (orientation, parent, name)
{
  m_dragging = m_changing_orientation = false;
  connect (this, TQ_SIGNAL (valueChanged (int)), this, TQ_SLOT (sliderValueChanged (int)));
}

KPlayerSlider::~KPlayerSlider()
{
#ifdef DEBUG_KPLAYER_SLIDERS
  kdDebugTime() << "KPlayerSlider destroyed\n";
#endif
}

TQSize KPlayerSlider::sizeHint() const
{
#ifdef DEBUG_KPLAYER_SLIDER_HINTS
  kdDebugTime() << "KPlayerSlider::sizeHint\n";
#endif
  TQSize hint = TQSlider::sizeHint();
  if ( KPlayerEngine::engine() )
  {
    int length = KPlayerEngine::engine() -> configuration() -> preferredSliderLength();
    if ( orientation() == TQt::Horizontal )
    {
      if ( hint.width() < length )
        hint.setWidth (length);
    }
    else
    {
      if ( hint.height() < length )
        hint.setHeight (length);
    }
  }
#ifdef DEBUG_KPLAYER_SLIDER_HINTS
  kdDebugTime() << " Hint   " << hint.width() << "x" << hint.height() << "\n";
#endif
  return hint;
}

TQSize KPlayerSlider::minimumSizeHint() const
{
#ifdef DEBUG_KPLAYER_SLIDER_HINTS
  kdDebugTime() << "KPlayerSlider::minimumSizeHint\n";
#endif
  TQSize hint = TQSlider::minimumSizeHint();
  if ( KPlayerEngine::engine() )
  {
    int length = KPlayerEngine::engine() -> configuration() -> minimumSliderLength();
    if ( orientation() == TQt::Horizontal )
    {
      if ( hint.width() < length )
        hint.setWidth (length);
    }
    else
    {
      if ( hint.height() < length )
        hint.setHeight (length);
    }
  }
#ifdef DEBUG_KPLAYER_SLIDER_HINTS
  kdDebugTime() << " Hint   " << hint.width() << "x" << hint.height() << "\n";
#endif
  return hint;
}

void KPlayerSlider::setOrientation (Orientation o)
{
  if ( o == orientation() )
    return;
  m_changing_orientation = true;
  int minValue = TQSlider::minValue();
  int maxValue = TQSlider::maxValue();
  int value = TQSlider::value();
  TQSlider::setOrientation (o);
  TQSlider::setMinValue (- maxValue);
  TQSlider::setMaxValue (- minValue);
  TQSlider::setValue (- value);
  m_changing_orientation = false;
}

int KPlayerSlider::minValue (void) const
{
  if ( orientation() == TQt::Horizontal )
    return TQSlider::minValue();
  return - TQSlider::maxValue();
}

void KPlayerSlider::setMinValue (int minValue)
{
  if ( orientation() == TQt::Horizontal )
    TQSlider::setMinValue (minValue);
  else
    TQSlider::setMaxValue (- minValue);
}

int KPlayerSlider::maxValue (void) const
{
  if ( orientation() == TQt::Horizontal )
    return TQSlider::maxValue();
  return - TQSlider::minValue();
}

void KPlayerSlider::setMaxValue (int maxValue)
{
  if ( orientation() == TQt::Horizontal )
    TQSlider::setMaxValue (maxValue);
  else
    TQSlider::setMinValue (- maxValue);
}

int KPlayerSlider::value (void) const
{
  if ( orientation() == TQt::Horizontal )
    return TQSlider::value();
  return - TQSlider::value();
}

void KPlayerSlider::setValue (int value, int)
{
  if ( orientation() == TQt::Horizontal )
    TQSlider::setValue (value);
  else
    TQSlider::setValue (- value);
}

void KPlayerSlider::setup (int minValue, int maxValue, int value,
  bool tickMarks, int tickInterval, int pageStep, int lineStep)
{
  setMinValue (minValue);
  setMaxValue (maxValue);
  setLineStep (lineStep);
  setPageStep (pageStep);
  setTickmarks (tickMarks ? TQSlider::Both : TQSlider::NoMarks);
  setTickInterval (tickInterval);
  setValue (value);
  updateGeometry();
}

void KPlayerSlider::sliderValueChanged (int)
{
  if ( ! m_changing_orientation )
    emit changed (value());
}

void KPlayerSlider::mousePressEvent (TQMouseEvent* event)
{
  m_dragging = (event -> stateAfter() & (TQt::LeftButton | TQt::MidButton)) != 0;
#ifdef DEBUG_KPLAYER_SLIDERS
  kdDebugTime() << "Popup slider mouse press " << event -> state() << " -> " << event -> stateAfter() << " -> " << m_dragging << "\n";
#endif
  TQSlider::mousePressEvent (event);
}

void KPlayerSlider::mouseReleaseEvent (TQMouseEvent* event)
{
  m_dragging = (event -> stateAfter() & (TQt::LeftButton | TQt::MidButton)) != 0;
#ifdef DEBUG_KPLAYER_SLIDERS
  kdDebugTime() << "Popup slider mouse release " << event -> state() << " -> " << event -> stateAfter() << " -> " << m_dragging << "\n";
#endif
  TQSlider::mouseReleaseEvent (event);
}

void KPlayerSlider::keyPressEvent (TQKeyEvent* event)
{
  int key = event -> key();
  if ( key == Key_Left || key == Key_Right || (event -> state() & (ControlButton | AltButton | MetaButton)) != 0
    && (key == Key_Up || key == Key_Down || key == Key_PageUp || key == Key_PageDown
    || key == Key_Home || key == Key_End) )
  {
    event -> ignore();
    return;
  }
  TQSlider::keyPressEvent (event);
}

void KPlayerSlider::wheelEvent (TQWheelEvent* event)
{
  static int remainder = 0;
  static TQSlider* owner = 0;
  if ( owner != this )
  {
    owner = this;
    remainder = 0;
  }
  int delta = event -> delta();
  if ( orientation() != TQt::Horizontal )
    delta = - delta;
  delta *= (event -> state() & TQt::ControlButton) == TQt::ControlButton ? pageStep() : lineStep();
  int offset = (delta + remainder + (delta > 0 ? 60 : -60)) / 120;
  remainder += delta - offset * 120;
#ifdef DEBUG_KPLAYER_SLIDERS
  kdDebugTime() << "Slider wheel event: delta " << event -> delta() << " offset " << offset << " remainder " << remainder
    << " position " << event -> x() << "x" << event -> y() << " global " << event -> globalX() << "x" << event -> globalY()
    << " state " << event -> state() << " orientation " << event -> orientation() << " accepted " << event -> isAccepted()
    << " spontaneous " << event -> spontaneous() << "\n";
#endif
  if ( offset != 0 )
    TQSlider::setValue (TQSlider::value() + offset);
  event -> accept();
}
