/* ====================================================================
* 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 "TextLineNrWidget.h"
#include "PainterSetup.h"
#include "TextPositionCalculator.h"
#include "ScrollPositionCalculator.h"
#include "ColorId.h"
#include "sublib/Line.h"
#include "sublib/TextModel.h"
#include "sublib/ColorStorage.h"
#include "sublib/NullTextModel.h"
// sys
#include <stdio.h>
#include <algorithm>
#include <assert.h>
static int dashLinePad = 1;
static int borderPad = 3;
static NullTextModel NullText;
TextLineNrWidget::TextLineNrWidget( QWidget *parent, unsigned long flags, const char *name )
: QWidget( parent, name ), _flags(flags), _ypos(0)
{
_lnColumns = 3;
_lnLeftPad = borderPad;
_lnRightPad = borderPad;
setSizePolicy( QSizePolicy(QSizePolicy::Fixed,QSizePolicy::Expanding) );
setBackgroundMode( Qt::NoBackground );
setModel(&NullText);
}
TextLineNrWidget::~TextLineNrWidget()
{
}
void TextLineNrWidget::setModel( TextModel* model )
{
_model = model;
sc::Size lines = _model->getLineCnt();
char buf[16] = "";
_lnColumns = sprintf( buf, "%u", lines );
updateGeometry();
}
void TextLineNrWidget::setFlags( unsigned long flags )
{
_flags = flags;
}
void TextLineNrWidget::paintEvent( QPaintEvent *e )
{
QRect pr = e->rect();
// Qt/X11 does crash when pr is null
// todo: why is pr null?
if( pr.isNull() )
return;
PainterSetup ps(this,pr);
QPainter& pp = ps.getPainter();
pp.setPen( ColorStorage::getColor(ColorLineNrFg) );
pp.setBackgroundColor( ColorStorage::getColor(ColorLineNrBg) );
QFontMetrics m(font());
TextPositionCalculator tpc( m, pr, 0, _ypos );
int topLine = tpc.getTopLine();
int botLine = tpc.getBottomLine();
int lnDefWidth = sizeHint().width();
// calc the first line number we have to draw
// TODO
// we could optimize this if we would remember the first visible line
// and then count from there....
int clnr = 0;
int lineNr = clnr;
for( int y = -_ypos; y < tpc.getLineY(topLine); y += m.height(), clnr++ )
{
Line line = _model->getLine( clnr );
if( ! line.isEmpty() )
{
lineNr++;
}
}
for( int curLine = topLine; curLine <= botLine; curLine++ )
{
// clear line background
pp.eraseRect( 0, tpc.getLineY(curLine), lnDefWidth, tpc.getFontHeight() );
Line line = _model->getLine( curLine );
if( ! line.isEmpty() )
{
// draw right aligned line number
char lnBuf[32];
int lnLength = sprintf( lnBuf, "%d", ++lineNr );
int lnWidth = m.width( lnBuf, lnLength );
int textX = 0;
if( _flags & Right )
{
textX = lnDefWidth-lnWidth-_lnRightPad + 1;
}
if( _flags & Left )
{
textX = lnDefWidth-lnWidth-_lnRightPad-dashLinePad;
}
pp.drawText( textX, tpc.getTextY(curLine), lnBuf, lnLength );
}
}
int dashX = 0;
if( _flags & Right )
{
dashX = 0;
}
if( _flags & Left )
{
dashX = lnDefWidth - 1;
}
// draw dash line
pp.setPen( ColorStorage::getColor(ColorDashBg) );
pp.drawLine( dashX, pr.y(), dashX, pr.y()+pr.height() );
pp.setPen( ColorStorage::getColor(ColorDashFg) );
for( int d = pr.y()+(_ypos + pr.y())%2; d < pr.y()+pr.height(); d+=2 )
{
pp.drawPoint( dashX, d );
}
}
void TextLineNrWidget::setScrollPosY( int ypos )
{
ScrollPositionCalculator spc;
int oy = _ypos;
int ny = spc.calcPos( oy, ypos, height(), sizeHint().height() );
if( oy == ny )
{
return;
}
_ypos = ny;
super::scroll( 0, oy - _ypos );
}
QSize TextLineNrWidget::sizeHint() const
{
QFontMetrics m(font());
sc::Size width = m.width('x') * _lnColumns + _lnLeftPad + _lnRightPad + dashLinePad;
sc::Size height = m.height() * _model->getLineCnt();
return QSize( (int)width, (int)height );
}
syntax highlighted by Code2HTML, v. 0.9.1