/* ====================================================================
 * Copyright (c) 2007-2008  Martin Hauner
 *                          http://subcommander.tigris.org
 *
 * Subcommander is licensed as described in the file doc/COPYING, which
 * you should have received as part of this distribution.
 * ====================================================================
 */

// sc
#include "Splitter.h"
#include "util/String.h"

// qt
#include <QtCore/QEvent>
#include <QtGui/QSplitterHandle>
#include <QtGui/QMoveEvent>
#include <QtGui/QShowEvent>

/** Initial @a position of SplitterHandle. */
const int UnsetPos = -1;

/**
 * Custom splitter handle for @a Splitter widget. Hides or shows the @a First or
 * @a Last widget when double clicking on the handle.
 */
class SplitterHandle : public QSplitterHandle
{
  typedef QSplitterHandle super;

public:
  SplitterHandle( QSplitter* parent, Qt::Orientation orientation, Splitter::Hide hide )
    : super(orientation,parent), _hide(hide), _pos(UnsetPos), _visible(true)
  {
  } 

  void mouseDoubleClickEvent( QMouseEvent* e )
  {
    if( _visible )
    {
      setPos(getCurrentPos());
      moveSplitter(getHidePos());
    }
    else
      moveSplitter(getPos());

    _visible = !_visible;
  }

  /**
   * Get the hide position respecting the @a orientation and @c Splitter::Hide.
   */
  int getHidePos() const
  {
    if( _hide == Splitter::First )
    {
      return 0; 
    }
    else // Splitter::Last
    {
      return getParentSize() - getSize();
    }
  }

  /**
   * Get the size of the handle respecting the @a orientation. Ie. it returns
   * @c width() for @a horizontal and @c height() for @a vertical layout.
   */
  int getSize() const
  {
    if( orientation() == Qt::Vertical )
    {
      return height();
    }
    else // Qt::Horizontal
    {
      return width();
    }
  }

  /**
   * Get the handle position respecting the @a orientation. Ie. it returns
   * @c x() for @a horizontal and @c y() for @a vertical layout.
   */ 
  int getCurrentPos() const
  {
    if( orientation() == Qt::Vertical )
    {
      return y();
    }
    else // Qt::Horizontal
    {
      return x();
    }
  }

  /** Set the click position. */
  void setPos( int pos )
  {
    _pos = pos;
  }

  /** Get the click position. */
  int getPos() const
  {
    return _pos;
  }

  /**
   * Get the size of the handles parent respecting the @a orientation. Ie.
   * it returns @c width() for @a horizontal and @c height() for @a vertical
   * layout.
   */
  int getParentSize() const
  {
    if( orientation() == Qt::Vertical )
    {
      return ((QWidget*)parent())->height();
    }
    else // Qt::Horizontal
    {
      return ((QWidget*)parent())->width();
    }
  }

private:
  Splitter::Hide _hide;

  int            _pos;             ///< visible click position
  bool           _visible;         ///< splitter content is visible
};


///////////////////////////////////////////////////////////////////////////////

Splitter::Splitter( QWidget* parent, Hide hide ) : super(parent), _hide(hide),
_handle(NULL)
{
}

Splitter::Splitter( QWidget* parent, Qt::Orientation orientation, Hide hide )
: super(orientation,parent), _hide(hide), _handle(NULL)
{
}

QSplitterHandle* Splitter::createHandle()
{
  if( count() == 1 )
  {
    _handle = new SplitterHandle( this, orientation(), _hide );
    return _handle;
  }
  else
  {
    return new QSplitterHandle( orientation(), this );
  }
}

void Splitter::showHide( bool b )
{
  // assumes two widget for now...
  QList<int> s;

  if(b)
    s << length()/2 << length()/2;
  else
    s << (_hide == First ? 0 : length())
      << (_hide == First ? length() : 0);

  setSizes(s);
}

void Splitter::enableHide( bool b )
{
  if( _hide == First )
  {
    widget(0)->setEnabled(b);
  }
  else
  {
    widget(count()-1)->setEnabled(b);
  }

  _handle->setEnabled(b);
}

int Splitter::length()
{
  if( orientation() == Qt::Vertical )
  {
    return height();
  }
  else // Qt::Horizontal
  {
    return width();
  }
}
