#include "VButton.h"
#include <tqvbox.h>
#include <tqfont.h>
#include <tdeconfig.h>
#include <tdeapplication.h>
#include "Xutils.h"
#include <X11/XKBlib.h>


double VButton::pw=552.0;
double VButton::ph=235.0;

VButton::VButton(TQWidget *parent, const char *name): TQPushButton (parent,name)
{
	TDEConfig *cfg = TDEApplication::kApplication()->config();
	TQString keysC = cfg->readEntry("keysColor", "#f0f0f0");
	setColor(TQColor(keysC));
	setFocusPolicy(TQWidget::NoFocus);
	resize(30,30);
	press=false;
}

VButton::~VButton()
{
}

void VButton::setupTexts(Display *display)
{
	// normal text
	KeySym keysym_c = XkbKeycodeToKeysym(display, keycode, 0, 0);
	TQChar nc((uint)keysym2ucs(keysym_c));
	if (nc == '&')
	{
		setText("&&");
	}
	else
	{
		setText(nc);
	}

	// shift text
	keysym_c = XkbKeycodeToKeysym(display, keycode, 0, 1);
	TQChar sc = (uint)keysym2ucs(keysym_c);
	if (sc == '&')
	{
		setShiftText("&&");
	}
	else
	{
		setShiftText(sc);
	}

	// altGr text
	keysym_c = XkbKeycodeToKeysym(display, keycode, 0, 2);
	TQChar c = (uint)keysym2ucs(keysym_c);
	if (c == " ")
	{
		// use normal text in case altGr does not provide extra characters.
		// This is required at least on US keyboards, where altGr works as Alt.
		c = nc;
	}
	if (c == '&')
	{
		altGrText = "&&";
	}
	else
	{
		altGrText = c;
	}

	// altGr + shift text
	keysym_c = XkbKeycodeToKeysym(display, keycode, 0, 3);
	c = (uint)keysym2ucs(keysym_c);
	if (c == " ")
	{
		// use shift text in case altGr does not provide extra characters.
		// This is required at least on US keyboards, where altGr works as Alt.
		c = sc;
	}
	if (c == '&')
	{
		altGrShiftText = "&&";
	}
	else
	{
		altGrShiftText = c;
	}

	// caps + altGr text
	capsAltGrText = altGrText.upper();

	// caps + altGr + shift text
	capsAltGrShiftText = altGrShiftText.lower();
}

void VButton::shiftCapsAltGrPressed(bool shift, bool caps, bool altGrState)
{
	if (altGrState)
	{
		// If Caps is on, displayed alpha characters should be toggled from the AltGr case
		if (caps)
		{
			if (shift)
			{
				TQPushButton::setText(capsAltGrShiftText);
			}
			else
			{
				TQPushButton::setText(capsAltGrText);
			}
		}
		else if (shift)
		{
			TQPushButton::setText(altGrShiftText);
		}
		else
		{
			TQPushButton::setText(altGrText);
		}
	}
	else
	{
		if (isAlpha)
		{
			// Alpha button, both shift and caps affect its state
			if (caps && shift)
			{
				TQPushButton::setText(capsShiftText);
			}
			else if (caps)
			{
				TQPushButton::setText(capsText);
			}
			else if (shift)
			{
				TQPushButton::setText(shiftText);
			}
			else
			{
				TQPushButton::setText(normalText);
			}
		}
		else
		{
			// Non alpha button, only shift affects its state
			if (shift)
			{
				TQPushButton::setText(shiftText);
			}
			else
			{
				TQPushButton::setText(normalText);
			}
		}
	}
}

void VButton::setText(const TQString& text)
{
	// Need to set the pushbutton text to correctly handle those buttons which usually
	// don't change (tab, shift, caps, Fn, ...)
	TQPushButton::setText(text);
	normalText = text;
	capsText = text.upper();
	isAlpha = text.length() == 1 && capsText != normalText;
}

void VButton::setShiftText(const TQString& text)
{
	shiftText = text;
	// 'text' is normally uppercase here, so in most cases we need to set capsShiftText
	// to text.lower() to handle caps+shift correctly. Special cases like ç and Ç are
	// handled by using text.upper()
	if (text.lower() != text)
	{
		capsShiftText = text.lower();
	}
	else
	{
		capsShiftText = text.upper();
	}
}

void VButton::setColor(const TQColor &color)
{
	setPaletteBackgroundColor(color);
	// Need to set TQColorGroup::Button color as well, otherwise the actual
	// color of the key does not change until the next restart of the application.
	TQPalette plt = palette();
	plt.setColor(TQPalette::Active,   TQColorGroup::Button, color);
	plt.setColor(TQPalette::Inactive, TQColorGroup::Button, color);
	plt.setColor(TQPalette::Disabled, TQColorGroup::Button, color);
	setPalette(plt);
}

void VButton::setKeyCode(unsigned int keycode)
{
	this->keycode=keycode;
}

unsigned int VButton::getKeyCode()
{
	return this->keycode;
}

void VButton::sendKey()
{
	emit keyClick(keycode);
}

void VButton::reposition(int width, int height)
{
	double dx=pw/orig_size.x();
	double dy=ph/orig_size.y();
	double sdx=pw/orig_size.width();
	double sdy=ph/orig_size.height();
	move((int)(width/dx),(int)(height/dy));
	resize((int)(width/sdx), (int)(height/sdy));
}

void VButton::res()
{
	orig_size=geometry();
}

void VButton::enterEvent(TQEvent *e)
{
	TQPushButton::enterEvent(e);
	inside = true;
}

void VButton::leaveEvent(TQEvent *e)
{
	TQPushButton::leaveEvent(e);
	inside = false;
}

void VButton::mousePressEvent(TQMouseEvent *e)
{
	press=true;
	TQPushButton::mousePressEvent(e);
	if (!isToggleButton())
	{
		// non toggle buttons need to send the key here
		sendKey();
		startTimer(500);
	}
}

void VButton::mouseReleaseEvent(TQMouseEvent *e)
{
	press=false;
	TQPushButton::mouseReleaseEvent(e);
	if (hitButton(e->pos()) && isToggleButton())
	{
		// toggle buttons need to send the key here because the underlying pushbutton state
		// is only updated on mouse release
		sendKey();
	}
	killTimers();
	inrpt=false;                                                                        
}

void VButton::timerEvent(TQTimerEvent *)
{
	if (!press)
	{
		inrpt=false;
		return;
	}
	if (press && !inrpt)
	{
		inrpt=true;
		startTimer(120);
		return;
	}
	if (inside)
	{
		// Send key only if the mouse is still inside the button rectangle
		sendKey();
	}
}

#include "VButton.moc"