// 
// Description: 
//  Implementation for ShapeWidget and deriver classes ShapeForm and ShapeButton 
//
// Author: Valentin Heinitz, <heinitz(at)freenet(dot)de>, (C) 2005
//
// Copyright: This is GPL software, 
//            See License.txt file that comes with this distribution
//
//
#include "shapewidget.h"

#include <qbitmap.h>
#include <qstring.h>


/*!
  Constructor. Behaves like QWidget if created so.
*/
ShapeWidget::ShapeWidget( QWidget *p ):  
    QWidget(p)
{

}

ShapeWidget::ShapeWidget(QWidget * parent, const char * name, WFlags f)
  : QWidget( parent, name, f )
{
}
 
/*!
  Constructor. Creates ShapeWidget with the size if the Image and the shape 
  of the visible area of the Image.
*/
ShapeWidget::ShapeWidget( QWidget *p, const QImage  & iname, long tcol ):  
    QWidget(p)
{
	setShape( iname  , tcol);
}

/*!
  This is an overloaded member function, provided for convenience. 
  It behaves essentially like the above function.
  Constructor. Creates ShapeWidget with the size if the Image and the shape 
  of the visible area of the Image.
*/    
ShapeWidget::ShapeWidget( QWidget *p, const QString &iname, long tcol ):  
    QWidget(p)
{
	setShape( iname  , tcol);
}

/*!
  Sets or resets the shape.   
*/
void ShapeWidget::setShape( const QImage & img  , long tcol)
{
	setPaletteBackgroundPixmap( img );
	setWidgetShape( this, img, tcol);
}

/*!
  This is an overloaded member function, provided for convenience. 
  It behaves essentially like the above function.
  Sets or resets the shape.
*/
void ShapeWidget::setShape( const QString &iname, long tcol )
{
	QImage img( iname );
	setShape(img, tcol );
}


/*!
  Static member function. Sets or resets the shape of a given Widget, which can be any
  class derived from QWidget. 
  This function actually provides the whole functionality of shaping the widgets.
*/
void ShapeWidget::setWidgetShape( QWidget *widget, const QImage  &img, long tcol)
{
	if ( widget && !img.isNull() )
	{      
		QImage img32 = img.convertDepth(32);       
		int w= img32.width(), h = img32.height();
		widget->resize( w,h );
		QImage tmask = QImage( w, h, 1, 2, QImage::LittleEndian );
		tmask.setColor( 0, 0xffffff );
		tmask.setColor( 1, 0 );
		tmask.fill( 0xff );
		QRgb bg;
		// User defined transp. color not set. get it from pixel at 0x0
		if ( tcol == -1 )
		{
			bg = *((QRgb*)img.scanLine(0)+0) & 0x00ffffff ; // Pixel im Punkt 0x0
		}
		else // Use user defined color for transparency
		{
			bg = tcol & 0x00ffffff;
		}
      
		QRgb *p;
		QRgb p24;
		uchar * mp;
		int x,y;
		for ( y = 0; y < h; y++ ){
			for ( x = 0; x < w; x++ ){
				p= (QRgb *)img32.scanLine(y) + x ;
				p24 = (*p & 0x00ffffff );
				if (   p24 == bg    ){
					mp = tmask.scanLine(y);
					*(mp + (x >> 3)) &= ~(1 << (x & 7));
				}
				p++;
			}
		}
		QBitmap bm;
		bm = tmask;
		widget->setMask( bm );         
	}
}


/*!
  This is an overloaded member function, provided for convenience. 
  It behaves essentially like the above function.  
  Static member function. Sets or resets the shape of a given Widget, which can be any
  class derived from QWidget.   
*/
void ShapeWidget::setWidgetShape( QWidget *widget, const QString &iname, long tcol)
{   
	setWidgetShape(widget, QImage( iname ), tcol );
}



/*!
  Constructor. Behaves like a QWidget if created so.
*/
ShapeForm::ShapeForm( QWidget *p ):  ShapeWidget(p), _mpressed(false)
{
 
}

/*!
  Constructor. Creates ShapeForm with the size if the Image and the shape 
  of the visible area of the Image.
*/
ShapeForm::ShapeForm( QWidget *p, const QImage  & iname, long tcol ):  
    ShapeWidget(p), _mpressed(false)
{
	setShape( iname  , tcol);
}

/*!
  This is an overloaded member function, provided for convenience. 
  It behaves essentially like the above function.
  Constructor. Creates ShapeForm with the size if the Image and the shape 
  of the visible area of the Image.
*/  
ShapeForm::ShapeForm( QWidget *p, const QString &iname, long tcol ):  
    ShapeWidget(p), _mpressed(false)
{
	setShape( iname  , tcol);
}

/*!
  Reimplemented member function of QWidget. Moves ShapeForm if pressed mouse is moved. 
*/
void ShapeForm::mouseMoveEvent( QMouseEvent *e)
{
    if (e && _mpressed ){
		move( e->globalPos() - _mpos );
    }        
}

/*!
  Reimplemented member function of QWidget for moving ShapeForm if pressed mouse is moved. 
*/
void ShapeForm::mousePressEvent( QMouseEvent *e)
{
	_mpressed = true;
	_mpos = e->pos();
}


/*!
  Reimplemented member function of QWidget for moving ShapeForm if pressed mouse is moved. 
*/
void ShapeForm::mouseReleaseEvent( QMouseEvent *)
{
    _mpressed = false;
}
    






/*!
  Constructor. Behaves like QWidget if created so, but provides a signal clicked(int id).
*/
ShapeButton::ShapeButton( QWidget *p ):  ShapeWidget(p), _id(0), bEnable(true)
{
 
}
 
/*!
  Constructor. Creates ShapeButton with the size if the Image and the shape 
  of the visible area of the Image.
*/
ShapeButton::ShapeButton( QWidget *p, const QImage  & img, long tcol ):  
    ShapeWidget(p), _id(0), bEnable(true)
{
	setShape( img  , tcol);
}

/*!
  This is an overloaded member function, provided for convenience. 
  It behaves essentially like the above function.
  Constructor. Creates ShapeButton with the size if the Image and the shape 
  of the visible area of the Image.
*/ 
ShapeButton::ShapeButton( QWidget *p, const QString &iname, long tcol ):  
    ShapeWidget(p), _id(0), bEnable(true)
{
	setShape( iname  , tcol);
}

/*!
  Sets the Pixmap that is shown when the ShapeButton is pressed.  
*/
void ShapeButton::setPressedShape( const QImage & img  , long tcol)
{
	Q_UNUSED( tcol );
	_pimg =   img ;  
}

/*!
  This is an overloaded member function, provided for convenience. 
  It behaves essentially like the above function.
  Sets the Pixmap that is shown when the ShapeButton is pressed.  
*/
void ShapeButton::setPressedShape( const QString &iname, long tcol )
{
	Q_UNUSED( tcol );
	_pimg =  QImage ( iname );  
}

void ShapeButton::setMouseOverShape( const QImage & img  , long tcol)
{
	Q_UNUSED( tcol );
	_oimg =   img ;
}

void ShapeButton::setMouseOverShape( const QString &iname, long tcol)
{
	Q_UNUSED( tcol );
	_oimg = QImage ( iname );
}


/*!
  Sets or resets the shape.  
*/
void ShapeButton::setShape( const QImage & img  , long tcol)
{
	_rimg =  img ;
	ShapeWidget::setShape(  _rimg, tcol);
	repaint();
}

/*!
  This is an overloaded member function, provided for convenience. 
  It behaves essentially like the above function.
  Sets or resets the shape. 
*/
void ShapeButton::setShape( const QString &iname, long tcol )
{
	_rimg =  QImage( iname );
	ShapeWidget::setShape(  _rimg, tcol);
	repaint();
}

/*!
  Reimplemented member function of QWidget for animation effect 
  (switching between pressed/released pictures) and sending clicked(int) signal 
*/
void ShapeButton::mousePressEvent( QMouseEvent *)
{
	if ( bEnable )
	{
		grabMouse();
		if ( !_pimg.isNull()  )
		{
			setPaletteBackgroundPixmap( _pimg );
			setWidgetShape( this, _pimg);
			repaint();
		}
	}
}

/*!
  Reimplemented member function of QWidget for animation effect 
  (switching between pressed/released pictures) and sending clicked(int) signal 
*/
void ShapeButton::mouseReleaseEvent( QMouseEvent *)
{
	if ( bEnable )
	{
		releaseMouse(); 
		if ( !_rimg.isNull() )
		{
			setPaletteBackgroundPixmap( _rimg );	
			setWidgetShape( this, _rimg); 
		}
		emit clicked( _id );
		emit clicked();
	}
}

void ShapeButton::enterEvent( QEvent * )
{
	if ( !_oimg.isNull() && bEnable )
	{
		setPaletteBackgroundPixmap( _oimg );
		setWidgetShape( this, _oimg);
		repaint(); 
	} 
}

void ShapeButton::leaveEvent( QEvent * )
{
	if ( !_rimg.isNull() && bEnable )
	{
		setPaletteBackgroundPixmap( _rimg );	
		setWidgetShape( this, _rimg);
		repaint(); 
	} 
}

void ShapeButton::setDisabled()
{
	bEnable = false;
	if ( !_oimg.isNull() )
	{
		setPaletteBackgroundPixmap( _oimg );
		setWidgetShape( this, _oimg);
		repaint(); 
	} 
}

void ShapeButton::setEnabled()
{
	bEnable = true;
	if ( !_rimg.isNull() )
	{
		setPaletteBackgroundPixmap( _rimg );  
		setWidgetShape( this, _rimg);
		repaint(); 
	} 
}

#include "shapewidget.moc"
