/***************************************************************************
 *   Copyright (C) 2006 by Sascha Hlusiak                                  *
 *   Spam84@gmx.de                                                         *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU 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.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.             *
 ***************************************************************************/


#include <tqimage.h>
#include <tqtooltip.h>
#include <tqpainter.h>

#include "crystalclient.h"
#include "crystalbutton.h"
#include "buttonimage.h"
#include "imageholder.h"


CrystalButton::CrystalButton(CrystalClient *parent, const char *name,
				const TQString& tip, ButtonType type,
				ButtonImage *vimage)
: TQButton(parent->widget(), name), client_(parent), type_(type), image(vimage), lastmouse_(0)
{
	setBackgroundMode(NoBackground);
	resetSize(false);
	setCursor(arrowCursor);
	
	hover=first=last=false;
	animation=0.0;
	TQToolTip::add(this, tip);
	connect ( &animation_timer,TQ_SIGNAL(timeout()),this,TQ_SLOT(animate()));
}

CrystalButton::~CrystalButton()
{
}

void CrystalButton::resetSize(bool FullSize)
{
	if (FullSize || (image && image->drawMode==1))
	{
		setFixedSize(buttonSizeH(),factory->titlesize);
	}else setFixedSize(buttonSizeH(),buttonSizeV());
}

void CrystalButton::setBitmap(ButtonImage *newimage)
{
	image=newimage;
	repaint(false);
}

TQSize CrystalButton::sizeHint() const
{
	return TQSize(buttonSizeH(),buttonSizeV());
}

int CrystalButton::buttonSizeH() const
{
	int w=image?image->image_width:DEFAULT_IMAGE_SIZE;
	int h=image?image->image_height:DEFAULT_IMAGE_SIZE;
	int vS=image?image->vSpace:2;
	int hS=image?image->hSpace:2;
	return (factory->titlesize-1-vS>=h)?
		w+hS*2:
		(int)(((float)buttonSizeV()/(float)h)*(float)w)+hS;
}

int CrystalButton::buttonSizeV() const
{
	int h=image?image->image_height:DEFAULT_IMAGE_SIZE;
	int vS=image?image->vSpace:2;
	return (factory->titlesize-1-vS>h)?h:factory->titlesize-1-vS;
}

void CrystalButton::enterEvent(TQEvent *e)
{
	hover=true;
	if (factory->hovereffect)repaint(false);
	if (factory->animateHover)animation_timer.start(60);
	TQButton::enterEvent(e);
}

void CrystalButton::leaveEvent(TQEvent *e)
{
	hover=false;
	if (factory->hovereffect)repaint(false);
	if (factory->animateHover)animation_timer.start(80);
	TQButton::leaveEvent(e);
}

void CrystalButton::mousePressEvent(TQMouseEvent* e)
{
	lastmouse_ = e->button();
	int button;
	switch(e->button())
	{
	case TQt::LeftButton:
		button=TQt::LeftButton;
		break;
	case TQt::RightButton:
		if ((type_ == ButtonMax) || (type_ == ButtonMin) || (type_ == ButtonMenu) || (type_ == ButtonClose))
			button=TQt::LeftButton; else button=TQt::NoButton;
		break;
	case TQt::MidButton:
		if ((type_ == ButtonMax) || (type_ == ButtonMin))
			button=TQt::LeftButton; else button=TQt::NoButton;
		break;

	default:button=TQt::NoButton;
		break;
	}
	TQMouseEvent me(e->type(), e->pos(), e->globalPos(),button, e->state());
	TQButton::mousePressEvent(&me);
}

void CrystalButton::mouseReleaseEvent(TQMouseEvent* e)
{
	lastmouse_ = e->button();
	int button;
	switch(e->button())
	{
	case TQt::LeftButton:
		button=TQt::LeftButton;
		break;
	case TQt::RightButton:
		if ((type_ == ButtonMax) || (type_ == ButtonMin) || (type_ == ButtonMenu) || (type_==ButtonClose))
			button=TQt::LeftButton; else button=TQt::NoButton;
		break;
	case TQt::MidButton:
		if ((type_ == ButtonMax) || (type_ == ButtonMin))
			button=TQt::LeftButton; else button=TQt::NoButton;
		break;
	
	default:button=TQt::NoButton;
		break;
	}
	TQMouseEvent me(e->type(), e->pos(), e->globalPos(), button, e->state());
	TQButton::mouseReleaseEvent(&me);
}

void CrystalButton::drawButton(TQPainter *painter)
{
	if (!CrystalFactory::initialized()) return;

	TQColorGroup group;
	float dx, dy;
	int dm=0;

	TQPixmap pufferPixmap;
	pufferPixmap.resize(width(), height());
	TQPainter pufferPainter(&pufferPixmap);
	
	CrystalFactory *f=((CrystalFactory*)client_->factory());
	TQPixmap *background;
	if (f->transparency)background=f->image_holder->image(client_->isActive());
		else background=NULL;
	WND_CONFIG *wndcfg=client_->isActive()?&f->active:&f->inactive;

	if (background && !background->isNull())
	{
		TQRect r=rect();
		TQPoint p=mapToGlobal(TQPoint(0,0));
		r.moveBy(p.x(),p.y());
	
		pufferPainter.drawPixmap(TQPoint(0,0),*background,r);
	}else{
		group = client_->options()->colorGroup(KDecoration::ColorTitleBar, client_->isActive());
		pufferPainter.fillRect(rect(), group.background());
	}

	if (!wndcfg->overlay.isNull())
	{
		pufferPainter.drawTiledPixmap(rect(),wndcfg->overlay,TQPoint(x(),y()));
	}

	dm=0;
	if (image && (image->drawMode==1))dm=1;
	if (wndcfg->outlineMode)
	{
		// outline the frame
		pufferPainter.setPen(wndcfg->frameColor);

		if (wndcfg->outlineMode==2)pufferPainter.setPen(wndcfg->frameColor.dark(150));
		if (wndcfg->outlineMode==3)pufferPainter.setPen(wndcfg->frameColor.light(150));
		// top
		if ((client_->FullMax && client_->isShade() && (dm==0)) ||
			((dm==1)&&(!client_->FullMax || client_->isShade()))) pufferPainter.drawLine(0,0,width(),0);
		// left
		if (first && client_->FullMax && client_->isShade())pufferPainter.drawLine(0,0,0,height());

		if (wndcfg->outlineMode==2)pufferPainter.setPen(wndcfg->frameColor.light(150));
		if (wndcfg->outlineMode==3)pufferPainter.setPen(wndcfg->frameColor.dark(150));
		// bottom
		if (client_->isShade() && ((dm==1)||(client_->FullMax)))pufferPainter.drawLine(0,height()-1,width(),height()-1);
		
		// right
		if (last && client_->FullMax && client_->isShade())pufferPainter.drawLine(width()-1,0,width()-1,height());
	}
	if (wndcfg->inlineMode && (client_->FullMax||dm==1) && !client_->isShade())
	{
		// inline the frame
		if (wndcfg->inlineMode==1)pufferPainter.setPen(wndcfg->inlineColor);
		if (wndcfg->inlineMode==2)pufferPainter.setPen(wndcfg->inlineColor.dark(150));
		if (wndcfg->inlineMode==3)pufferPainter.setPen(wndcfg->inlineColor.light(150));
		// buttons just need to draw the bottom line
		pufferPainter.drawLine(0,height()-1,width(),height()-1);
	}


	if (type_ == ButtonMenu && (!::factory->menuImage || image==NULL || (image!=NULL && !image->initialized()))) {
		// we paint the mini icon (which is 16 pixels high)
		dx = float(width() - 16) / 2.0;
		dy = float(height() - 16) / 2.0;

		if (dx<1 || dy<=1)
		{
			int m=(rect().width()-2<rect().height())?rect().width()-2:rect().height();
			TQRect r((rect().width()-m)/2,(rect().height()-m)/2,m,m);
// 			if (isDown()) { r.moveBy(1,1); }
        		pufferPainter.drawPixmap(r, client_->icon().pixmap(TQIconSet::Small,
                                                           TQIconSet::Normal));
		}else{
//         	if (isDown()) { dx++; dy++; }
			pufferPainter.drawPixmap((int)dx, (int)dy, client_->icon().pixmap(TQIconSet::Small,
                                                           TQIconSet::Normal));
		}
	} else if (image && image->initialized()) {
		// otherwise we paint the deco
		dx = float(width() - image->image_width) / 2.0;
		dy = float(height() - image->image_height) / 2.0;
		
		TQImage *img=image->normal;

		if (::factory->hovereffect)
		{
			if (hover)
			{
				img=image->hovered; 
			}
			if (::factory->animateHover)
			{
				img=image->getAnimated(animation);
			}
		}
		if (isDown())
		{
			img=image->pressed;
		}
	
		if (img)
		if (dx<image->hSpace/2 || dy<0)
		{	// Deco size is smaller than image, we need to stretch it
			int w,h;

			if (rect().width()-image->hSpace<rect().height())
			{
				w=rect().width()-image->hSpace;
				h=(int)((float)w*(float)image->image_height/(float)image->image_width);
			}else{
				h=rect().height();
				w=(int)((float)h*(float)image->image_width/(float)image->image_height);
			}

			TQRect r((rect().width()-w)/2,(rect().height()-h)/2,w,h);

			pufferPainter.drawImage(r,*img);
			if (type_ == ButtonMenu) drawMenuImage(&pufferPainter, r);
		}else{
			// Otherwise we just paint it
			if (image->drawMode==1)dy=0;
			pufferPainter.drawImage(TQPoint((int)dx,(int)dy),*img);

			if (type_ == ButtonMenu) drawMenuImage(&pufferPainter, 
				TQRect((int)dx,(int)dy,image->image_width,image->image_height));
	    }
	}
	
	pufferPainter.end();
	painter->drawPixmap(0,0, pufferPixmap);
}

void CrystalButton::drawMenuImage(TQPainter* painter, TQRect r)
{
	if (type_ != ButtonMenu) return;
	// we paint the mini icon (which is 16 pixels high)
	r.setTop(r.top()+1);
	r.setBottom(r.bottom()-1);
	float dx = float(r.width() - 16) / 2.0;
	float dy = float(r.height() - 16) / 2.0;
		
	if (dx<1 || dy<=1)
	{
		int m=(r.width()-2<r.height())?r.width()-2:r.height();
		TQRect r2(r.left()+(r.width()-m)/2,r.top()+(r.height()-m)/2,m,m);
		painter->drawPixmap(r2, client_->icon().pixmap(TQIconSet::Small,
								TQIconSet::Normal));
	}else{
		painter->drawPixmap(r.left()+(int)dx, r.top()+(int)dy, client_->icon().pixmap(TQIconSet::Small,
									TQIconSet::Normal));
	}
}

void CrystalButton::animate()
{
	if (hover)
	{
		animation+=0.25;
		if (animation>1.0)
		{
			animation=1.0;
			animation_timer.stop();
		}
	}else{
		animation-=0.15;
		if (animation<0.0)
		{
			animation=0.0;
			animation_timer.stop();
		}
	}
	repaint(false);
}

#include "crystalbutton.moc"
