/* ====================================================================
 * Copyright (c) 2003-2007, 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 "ConflictMarkerWidget.h"

// sys
#include <stdio.h>

// qt
#include <QtGui/QPainter>
#include <QtGui/QPixmap>
#include <QtGui/QMenu>
#include <QtGui/QMouseEvent>


static const int   Pad = 2;
static const QChar MarkLeft('<');
static const QChar MarkRight('>');

QColor ConflictMarkerWidget::_bgConflict(255,210,210);
//QColor ConflictMarkerWidget::_bgConflict(210,210,255);
QColor ConflictMarkerWidget::_bgSolved(255,255,255);
QColor ConflictMarkerWidget::_fg(0,0,0);

static long stateOrder[] = 
{
  ConflictMarkerWidget::None,
  ConflictMarkerWidget::Left,
  ConflictMarkerWidget::Right,
  ConflictMarkerWidget::LeftLeftTop   | ConflictMarkerWidget::Right,
  ConflictMarkerWidget::RightRightTop | ConflictMarkerWidget::Left 
};

ConflictMarkerWidget::ConflictMarkerWidget( QWidget * parent, const char * name )
: QWidget(parent,name), _columns(2), _conflict(0), _state(None)
{
  setSizePolicy( QSizePolicy( QSizePolicy::Fixed, QSizePolicy::Fixed ) );

  _popup = new QMenu(this);
  _popup->addAction( _q("resolve") );
  _popup->insertSeparator();
  _popup->addAction( _q("left") );
  _popup->addAction( _q("right") );
  _popup->addAction( _q("both") );
}


ConflictMarkerWidget::~ConflictMarkerWidget()
{
}

QSize ConflictMarkerWidget::sizeHint() const
{
  QFontMetrics m = fontMetrics();

  int h = m.height(); // + 2*m.descent();
  int w = m.width('8')*(_columns+2) + 4*Pad;
  return QSize( w, h );
}

void ConflictMarkerWidget::setConflict( int i )
{
  _conflict = i;
}

void ConflictMarkerWidget::focusInEvent( QFocusEvent* e ) 
{
  super::focusInEvent(e);
}

void ConflictMarkerWidget::mousePressEvent( QMouseEvent* e )
{
  if( e->button() == Qt::LeftButton )
  {
    // the array is short enough to simply iterate over it
    // to find the current state..
    for( int i = 0; i < (int)sizeof(stateOrder); i++ )
    {
      if( _state == stateOrder[i] )
      {
        _state = stateOrder[ (i+1)%sizeof(stateOrder) ];
        update();
        // emit stateChanged
        break;
      }
    }
  }
  else if( e->button() == Qt::RightButton )
  {
    _popup->popup( mapToGlobal(e->pos()) );
  }
}

void ConflictMarkerWidget::paintEvent( QPaintEvent *e )
{
  QRect    pr = e->rect(); 
  QPixmap  pm( e->rect().width(), e->rect().height() );

  QPainter pp(/*this*/&pm);
  // this lets us draw with the same coordinates into the buffer
  // we use to draw into the window.
  pp.translate( -pr.x(), -pr.y() );

  pp.setFont(font());
  pp.setPen( _fg );
  if( _state == ConflictMarkerWidget::None )
  {
    pp.setBackgroundColor( _bgConflict );
  }
  else
  {
    pp.setBackgroundColor( _bgSolved );
  }

  QFontMetrics m = fontMetrics();
  QSize        s = sizeHint();

  pp.eraseRect( 0, 0, s.width(), s.height() );

  // draw centered line number
  char lnBuf[32];
  sprintf( lnBuf, "%d", _conflict );

  pp.drawText( 0, 0, s.width(), s.height(), Qt::AlignHCenter | Qt::AlignVCenter, lnBuf );

  if( _state & Left )
  {
    int h = s.height();

    if( _state & LeftTop )
    {
      h -= m.descent();
    }
    int w = m.width(MarkLeft)+2*Pad;

    pp.drawText( 0, 0, w , h, Qt::AlignHCenter | Qt::AlignVCenter, MarkLeft );
  }

  if( _state & Right )
  {
    int h = s.height();

    if( _state & RightTop )
    {
      h -= m.descent();
    }
    int w = m.width(MarkRight)+2*Pad;

    pp.drawText( s.width()-w, 0, w, h, Qt::AlignHCenter | Qt::AlignVCenter, MarkRight );
  }

  // done with drawing, copy buffer
  pp.end();
  bitBlt( this, pr.topLeft(), &pm );
}

void ConflictMarkerWidget::resizeEvent( QResizeEvent *e )
{
  super::resizeEvent(e);
}

