/* ====================================================================
 * Copyright (c) 2003-2006, 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 "config.h"
#include "DoubleTextWidget.h"
#include "TextWidget.h"
#include "TextLineNrWidget.h"
#include "TextGlueWidget.h"
#include "sublib/TextModel.h"
#include "sublib/TextModelImpl.h"
#include "sublib/Line.h"
#include "util/String.h"

// qt
#include <qgrid.h>
#include <qhbox.h>
#include <qvbox.h>
#include <qlayout.h>
#include <qscrollbar.h>
#include <qsplitter.h>
#include <qlineedit.h>
#include <qlabel.h>
#include <qtooltip.h>
#include <qcheckbox.h>

// sys
#include <stdio.h>
#include <algorithm>



DoubleTextWidget::DoubleTextWidget( QWidget *parent, const char *name )
: super( parent, name )
{
  // base class layout
  QGridLayout* gl = (QGridLayout*)layout();
  {
    QWidget*     iw  = new QWidget(this);
    QGridLayout* mgl = new QGridLayout( iw, 4, 4 );
    mgl->setMargin( 2 );
    mgl->setSpacing( 2 );
    gl->addWidget( iw, 0, 0 );
    {
      // first row, left
      _lLabel = new QLineEdit(iw);
      _lLabel->setText( _q("left...") );
      _lLabel->setFrameStyle( QFrame::Panel | QFrame::Sunken );
      _lLabel->setLineWidth( 1 );
      //_lLabel->setMinimumWidth( 0 );
      _lLabel->setReadOnly(true);
      _lLabel->setMargin(1);
      _lLabel->setBackgroundMode( PaletteButton );
      _lLabel->setSizePolicy( QSizePolicy(QSizePolicy::Expanding,QSizePolicy::Fixed) );
      mgl->addWidget( _lLabel, 0, 0 );

      QHBox* h = new QHBox(iw);
      mgl->addMultiCellWidget( h, 0, 0, 1, 2 );
      {
        _checkLeft = new QCheckBox(h);
        _checkLeft->toggle();

        _checkLong = new QCheckBox(h);

        _checkRight = new QCheckBox(h);
        _checkRight->toggle();
      }

      connect( _checkLeft, SIGNAL(toggled(bool)), SLOT(toggleLeft(bool)) );
      connect( _checkRight, SIGNAL(toggled(bool)), SLOT(toggleRight(bool)) );
      connect( _checkLong, SIGNAL(toggled(bool)), SLOT(toggleLong(bool)) );

      // first row, right
      _rLabel = new QLineEdit(iw);
      _rLabel->setText( _q("right...") );
      _rLabel->setFrameStyle( QFrame::Panel | QFrame::Sunken );
      _rLabel->setLineWidth( 1 );
      //_rLabel->setMinimumWidth( 0 );
      _rLabel->setReadOnly(true);
      _rLabel->setMargin(1);
      _rLabel->setBackgroundMode( PaletteButton );
      _rLabel->setSizePolicy( QSizePolicy(QSizePolicy::Expanding,QSizePolicy::Fixed) );
      mgl->addWidget( _rLabel, 0, 3 );

      // second, all
      QFrame* f = new QFrame(iw);
      f->setFrameStyle( QFrame::HLine | QFrame::Sunken );
      f->setLineWidth(1);
      mgl->addMultiCellWidget( f, 1, 1, 0, 3 );

      // third, all
      QHBox* mltb = new QHBox(iw);
      mltb->setBackgroundMode( QWidget::NoBackground );
      mltb->setSizePolicy( QSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding) );
      mltb->setMargin(0);
      mltb->setSpacing(0);
      mgl->addMultiCellWidget( mltb, 2, 2, 0, 3 );
      {
        _lLines = new TextLineNrWidget(mltb);
        _left   = new TextWidget(mltb);

        _glue   = new TextGlueWidget(mltb);

        _right  = new TextWidget(mltb);
        _rLines = new TextLineNrWidget( mltb, TextLineNrWidget::Right );

        //_left->setMouseTracking(true);
        //_right->setMouseTracking(true);
      }

      // fourth, all
      _long = new QVBox(iw);
      _long->hide();
      //vb->setBackgroundMode( QWidget::NoBackground );
      //vb->setSizePolicy( QSizePolicy(QSizePolicy::Expanding,QSizePolicy::Fixed) );
      _long->setFrameStyle( QFrame::Box | QFrame::Plain );
      _long->setLineWidth(1);
      _long->setSpacing(1);
      mgl->addMultiCellWidget( _long, 3, 3, 0, 3 );
      {
        TextModelImpl* lm = new TextModelImpl( _s("left") );
        TextModelImpl* rm = new TextModelImpl( _s("right") );

        _l = new TextWidget(_long);
        _l->enableRightColMark(false);
        _l->setModel(lm,rm);
        _l->setModelSize( 0, 1 );
        _l->setSizePolicy( QSizePolicy(QSizePolicy::Expanding,QSizePolicy::Fixed) );

        _r = new TextWidget(_long);
        _r->enableRightColMark(false);
        _r->setModel(rm,lm);
        _r->setModelSize( 0, 1 );
        _r->setSizePolicy( QSizePolicy(QSizePolicy::Expanding,QSizePolicy::Fixed) );
      }
    }
  }

  connect( _left, SIGNAL(xChanged(int)), SLOT(xChange(int)) );
  connect( _left, SIGNAL(yChanged(int)), SLOT(yChange(int)) );
  connect( _right, SIGNAL(xChanged(int)), SLOT(xChange(int)) );
  connect( _right, SIGNAL(yChanged(int)), SLOT(yChange(int)) );

  connect( _left, SIGNAL(mouseLine(int)), SLOT(mouseLine(int)) );
  connect( _right, SIGNAL(mouseLine(int)), SLOT(mouseLine(int)) );
}

DoubleTextWidget::~DoubleTextWidget()
{
}

void DoubleTextWidget::setModel( TextModel* left, TextModel* right )
{
  _left->setModel( left, right );
  _lLines->setModel( left );
  _lLabel->setText( left->getSourceName().getStr() );
  QToolTip::add( _lLabel, left->getSourceName().getStr() );

  _right->setModel( right, left );
  _rLines->setModel( right );
  _rLabel->setText( right->getSourceName().getStr() );
  QToolTip::add( _rLabel, right->getSourceName().getStr() );

  sc::Size cols = 0;
  if( left->getColumnCnt()  > cols ) cols = left->getColumnCnt();
  if( right->getColumnCnt() > cols ) cols = right->getColumnCnt();

  sc::Size lines = 0;
  if( left->getLineCnt()  > lines ) lines = left->getLineCnt();
  if( right->getLineCnt() > lines ) lines = right->getLineCnt();

  _left->setModelSize( cols, lines );
  _right->setModelSize( cols, lines );
  _glue->setLineCnt( lines );
  _glue->setModel( left, right );
}

void DoubleTextWidget::setModel( DiffInfoModel* info )
{
  _glue->setModel(info);
}

void DoubleTextWidget::setLeftLabel( const sc::String& l )
{
  if( l.getCharCnt() > 0 )
  {
    _lLabel->setText( (const char*)l );
  }
}

void DoubleTextWidget::setRightLabel( const sc::String& r )
{
  if( r.getCharCnt() > 0 )
  {
    _rLabel->setText( (const char*)r );
  }
}

void DoubleTextWidget::vsbChange(int y)
{
  _left->setScrollPosY(y);
  _lLines->setScrollPosY(y);

  _glue->setScrollPosY(y);

  _right->setScrollPosY(y);
  _rLines->setScrollPosY(y);
}

void DoubleTextWidget::hsbChange(int x)
{
  _left->setScrollPosX(x);
  _right->setScrollPosX(x);
}

void DoubleTextWidget::xChange(int x)
{
  if( _hsb->value() == x )
  {
    return;
  }

  _hsb->setValue(x);
}

void DoubleTextWidget::yChange(int y)
{
  if( _vsb->value() == y )
  {
    return;
  }

  _vsb->setValue(y);
}

void DoubleTextWidget::toggleLeft(bool show)
{
  if( ! show )
  {
    _lLines->hide();
    _left->hide();
    _checkRight->setEnabled(false);
  }
  else
  {
    _lLines->show();
    _left->show();
    _checkRight->setEnabled(true);
  }
}

void DoubleTextWidget::toggleRight(bool show)
{
  if( ! show )
  {
    _rLines->hide();
    _right->hide();
    _checkLeft->setEnabled(false);
  }
  else
  {
    _rLines->show();
    _right->show();
    _checkLeft->setEnabled(true);
  }
}

void DoubleTextWidget::toggleLong(bool show)
{
  if( ! show )
  {
    _long->hide();
  }
  else
  {
    _long->show();
  }
}

void DoubleTextWidget::mouseLine(int y)
{
  if( _long->isHidden() )
  {
    return;
  }

  Line l = _left->getModel()->getLine(y);
  Line r = _right->getModel()->getLine(y);

  TextModelImpl* lm = dynamic_cast<TextModelImpl*>(_l->getModel());
  lm->clear();
  lm->addLine(l);

  TextModelImpl* rm = dynamic_cast<TextModelImpl*>(_r->getModel());
  rm->clear();
  rm->addLine(r);

  _l->update();
  _r->update();
}

QSize DoubleTextWidget::getScrollSizeHint()
{
  // this one is used by our superclass to size the scrollbar
  // since we can hide our text widgets we have to return the
  // values from the visible one.
  if( _left->isVisible() )
  {
    return _left->sizeHint();
  }
  else
  {
    return _right->sizeHint();
  }
}

QSize DoubleTextWidget::getScrollSizeCurr()
{
  // this one is used by our superclass to size the scrollbar
  // since we can hide our text widgets we have to return the
  // values from the visible one.
  if( _left->isVisible() )
  {
    return _left->size();
  }
  else
  {
    return _right->size();
  }
}

TextWidget* DoubleTextWidget::getLeftText() const
{
  return _left;
}

TextWidget* DoubleTextWidget::getRightText() const
{
  return _right;
}

void DoubleTextWidget::jumpToLine( int line )
{
  int ypos = _left->calcLineY(line,true);

  if( _vsb->value() == ypos )
  {
    return;
  }

  _vsb->setValue(ypos);
}

void DoubleTextWidget::jumpToBlock( int block )
{
  BlockInfo li = _left->getModel()->getBlockInfo( block );
  BlockInfo ri = _right->getModel()->getBlockInfo( block );

  if( ! li.isEmpty() )
  {
    jumpToLine( li.getStart() );
    return;
  }

  if( ! ri.isEmpty() )
  {
    jumpToLine( ri.getStart() );
    return;
  }
}

void DoubleTextWidget::setActiveDiff( int num )
{
  _glue->setActiveDiff(num);
}

void DoubleTextWidget::setAcceptDrops(bool on)
{
  _left->setAcceptDrops(true);
  _right->setAcceptDrops(true);
}


syntax highlighted by Code2HTML, v. 0.9.1