
#include "echklist.h"
/*  
	echklist.cpp V0.4.1 June 1998
	
	Requires the Qt widget libraries, available at no cost at 
    http://www.troll.no
       
    Copyright (C) 1998 Bernd Schumacher & Othmar Ehrhardt
                       Bernd_Schumacher@fh-konstanz.de

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

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.
*/

ECheckListItem::ECheckListItem( const char *s, const QPixmap p, bool doCheck,
	bool doEnable ) : QListBoxItem()
{ 
	setText( s ); 
	pm=p;
	checked=doCheck;
	enabled=doEnable;
}

ECheckListItem::~ECheckListItem()
{
}

void ECheckListItem::paint( QPainter *p )
{
	p->save();
    p->drawPixmap( 1, 0, pm );
    QFontMetrics fm = p->fontMetrics();
    int yPos;                       // vertical text position
    if ( pm.height() < fm.height() )
       yPos = fm.ascent() + fm.leading()/2;
    else
       yPos = pm.height()/2 - fm.height()/2 + fm.ascent();
	if ( !isEnabled() ) p->setPen( gray );
    p->drawText( pm.width() + 21, yPos, text() );
	p->restore();
}

int ECheckListItem::height(const QListBox *lb ) const
{
        return QMAX( pm.height()+1, lb->fontMetrics().lineSpacing() + 1 );
}

int ECheckListItem::width(const QListBox *lb ) const
{
        return pm.width() + lb->fontMetrics().width( text() ) + 6;
}

QRect ECheckListItem::boundingRect( QPainter *p )
{
	QFontMetrics fm = p->fontMetrics();
	int rectX=19+pm.width();
	int rectY;
        if ( pm.height() < fm.height() )
        	rectY = 0;
        else
        	rectY = pm.height()/2 - fm.height()/2;
	int rectW=fm.width(text())+5;
	int rectH=fm.height()+1;
	return QRect ( rectX, rectY, rectW, rectH );
}

ECheckList::ECheckList( QWidget* parent, const char* name, WFlags f )
			: QListBox( parent, name, f )
{
	QListBox::setMultiSelection( FALSE );
}

ECheckList::~ECheckList()
{
}

void ECheckList::paintCell( QPainter *p, int row, int )
{
    ECheckListItem *lbi = (ECheckListItem *) item( row );
    if ( !lbi ) return;

	p->save();
    QColorGroup g = colorGroup();
    QRect br=lbi->boundingRect( p );			//bounding Rect for Item Text
	if ( isSelected( row ) && lbi->isEnabled() ) {
		QColor	 fc;							//fill color
		if ( style() == WindowsStyle )
			fc = QApplication::winStyleHighlightColor();
		else fc = g.text();
		p->fillRect( br, fc );
		p->setPen( style() == WindowsStyle ? white : g.base() );
		p->setBackgroundColor( fc );
	} else {
		p->setBackgroundColor( g.base() );
		p->setPen( g.text() );
    } 
	lbi->paint( p );
    const QPixmap *pm=lbi->pixmap();
    if ( currentItem() == row && hasFocus() ) {
		if ( style() == WindowsStyle ) {
			if ( lbi->isEnabled() ) 
	    		p->drawWinFocusRect( br.x()+1, br.y()+1 , br.width()-2, 
					br.height()-2, QApplication::winStyleHighlightColor() );
			else p->drawWinFocusRect( br.x()+1, br.y()+1 , br.width()-2,
					br.height()-2, gray );
		} else {
	    	if ( isSelected( row ) ) p->setPen( g.base() );
	    	else p->setPen( g.text() );
			if ( !lbi->isEnabled() ) p->setPen( gray );
	    	p->setBrush( NoBrush );
	    	p->drawRect( br.x()+1, br.y()+1 , br.width()-2, br.height()-2 );
		}
    }
	int x=4+pm->width(), y=2, w=12, h=12;
	p->setBrush( g.base() );
	if ( lbi->isEnabled() ) p->setPen( black );
	else p->setPen( gray );
	p->drawRect ( x, y, w, h );	//draw checkbox
	if ( lbi->isChecked() ) {
	    QPointArray a( 7*2 );
	    int i, xx, yy;
	    xx = x+3;
	   	yy = y+5;
	   	for ( i=0; i<3; i++ ) {
			a.setPoint( 2*i,   xx, yy );
			a.setPoint( 2*i+1, xx, yy+2 );
			xx++; yy++;
	   	}
	   	yy -= 2;
	   	for ( i=3; i<7; i++ ) {
			a.setPoint( 2*i,   xx, yy );
			a.setPoint( 2*i+1, xx, yy+2 );
			xx++; yy--;
    	}
	   	p->drawLineSegments( a );
	}
	p->restore();
}

void ECheckList::mousePressEvent( QMouseEvent *e )
{
    int itemClicked = findItem( e->pos().y() );
    if ( itemClicked != -1 ) {
		ECheckListItem *tmp=(ECheckListItem *) item(itemClicked);
		const QPixmap *pm=tmp->pixmap();
		if ( e->pos().x() < 20+pm->width() && e->pos().x() >2+pm->width() ) {
			if ( tmp->isEnabled() ) {
				tmp->setChecked( !tmp->isChecked() );
				emit ECheckList::toggled( itemClicked, tmp->isChecked() );
				QString buffer=tmp->text();
				if ( !buffer.isEmpty() ) emit toggled( buffer.data(),
						tmp->isChecked() );
				repaint();
			}
    	} else {
			setCurrentItem( itemClicked );
			toggleCurrentItem();
		}
	} else if ( contentsRect().contains( e->pos() ) && lastRowVisible() >= (int) count() ) {
//		if ( e->pos().x() < 18 ) {
		if ( e->pos().x() < 36 && e->pos().x() >19 ) {
			ECheckListItem *tmp=(ECheckListItem *) item( count()-1 );
			if ( tmp->isEnabled() ) {
				tmp->setChecked( !tmp->isChecked() );
				emit ECheckList::toggled( itemClicked, tmp->isChecked() );
				QString buffer=tmp->text();
				if ( !buffer.isEmpty() ) emit ECheckList::toggled( buffer.data(),
						tmp->isChecked() );
				repaint();
			}
     	} else {
			setCurrentItem( count()-1 );
			toggleCurrentItem();
		}
    }
}

void ECheckList::keyPressEvent( QKeyEvent *e )
{
    if ( numRows() == 0 )
	return;
    if ( currentItem() < 0 ) setCurrentItem( topItem() );

    switch ( e->key() ) {
    case Key_Return:
    case Key_Enter:
	if ( currentItem() >= 0 ) {
		ECheckListItem *tItem=(ECheckListItem *) item ( currentItem() );
		if ( tItem->isEnabled() ) {
	    	QString tmp = item( currentItem() )->text();
	    	emit selected( currentItem());
	    	if ( !tmp.isEmpty() )
			emit selected( tmp );
		}
	}
	break;
	case Key_Space:
	if ( currentItem() >= 0 ) {
		ECheckListItem *cItem=(ECheckListItem *) item ( currentItem() );
		if ( cItem->isEnabled() ) {
	    	QString tmp = cItem->text();
	    	emit highlighted( currentItem());
			cItem->setChecked(!cItem->isChecked());
			emit ECheckList::toggled( currentItem(), cItem->isChecked() );
			repaint();
	    	if ( !tmp.isEmpty() ) {
				emit highlighted( tmp.data() );
				emit ECheckList::toggled( tmp.data(), cItem->isChecked() );
			}
		}
	}
	break;
    default:
	QListBox::keyPressEvent( e );
	break;
	}
}

bool ECheckList::isChecked( int row )
{
	if ( row<0 || row>(int) count()-1 ) {
		warning ("ECheckList::isChecked out of range");
		return FALSE;
	}
	ECheckListItem *tmp=(ECheckListItem *) item( row );
	return tmp->isChecked();
}

bool ECheckList::isChecked( const char *t )
{
	for ( uint i=0; i<count(); i++ ) {
		ECheckListItem *tmp=(ECheckListItem *) item( i );
		QString buffer=tmp->text();
		if ( buffer==t ) {
			return tmp->isChecked();
		}
	}
	warning ("ECheckList::isChecked <%s> not found", t);
	return FALSE;
}

void ECheckList::setChecked( int row, bool check )
{
	if ( row>=(int) count() ) {
		warning("ECheckList::setChecked %d out of range", row);
		return;
	}
	ECheckListItem *tmp=(ECheckListItem *) item( row );
	tmp->setChecked( check );
	repaint();
}	

void ECheckList::setEnabled( int row, bool enable )
{
	if ( row>=(int) count() ) {
		warning("ECheckList::setEnabled %d out of range", row);
		return;
	}
	ECheckListItem *tmp=(ECheckListItem *) item( row );
	tmp->setEnabled( enable );
	repaint();
}	

bool ECheckList::isEnabled( int row )
{
	if ( row>=(int) count() ) {
		warning("ECheckList::isEnabled %d out of range", row);
		return FALSE;
	}
	ECheckListItem *tmp=(ECheckListItem *) item( row );
	if ( tmp->isEnabled() ) return TRUE;
	return FALSE;
}

