#include "CGUIButton.h"
#ifdef _IRR_COMPILE_WITH_GUI_
#include "IGUISkin.h"
#include "IGUIEnvironment.h"
#include "IVideoDriver.h"
#include "IGUIFont.h"
#include "os.h"
namespace irr
{
namespace gui
{
CGUIButton::CGUIButton(IGUIEnvironment* environment, IGUIElement* parent,
s32 id, core::rect<s32> rectangle, bool noclip)
: IGUIButton(environment, parent, id, rectangle),
SpriteBank(0), OverrideFont(0), Image(0), PressedImage(0),
ClickTime(0), IsPushButton(false), Pressed(false),
UseAlphaChannel(false), DrawBorder(true), ScaleImage(false)
{
#ifdef _DEBUG
setDebugName("CGUIButton");
#endif
setNotClipped(noclip);
for (u32 i=0; i<EGBS_COUNT; ++i)
ButtonSprites[i].Index = -1;
setTabStop(true);
setTabOrder(-1);
}
CGUIButton::~CGUIButton()
{
if (OverrideFont)
OverrideFont->drop();
if (Image)
Image->drop();
if (PressedImage)
PressedImage->drop();
if (SpriteBank)
SpriteBank->drop();
}
void CGUIButton::setScaleImage(bool scaleImage)
{
ScaleImage = scaleImage;
}
bool CGUIButton::isScalingImage() const
{
_IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX;
return ScaleImage;
}
void CGUIButton::setDrawBorder(bool border)
{
DrawBorder = border;
}
void CGUIButton::setSpriteBank(IGUISpriteBank* sprites)
{
if (sprites)
sprites->grab();
if (SpriteBank)
SpriteBank->drop();
SpriteBank = sprites;
}
void CGUIButton::setSprite(EGUI_BUTTON_STATE state, s32 index, video::SColor color, bool loop)
{
if (SpriteBank)
{
ButtonSprites[(u32)state].Index = index;
ButtonSprites[(u32)state].Color = color;
ButtonSprites[(u32)state].Loop = loop;
}
else
{
ButtonSprites[(u32)state].Index = -1;
}
}
bool CGUIButton::OnEvent(const SEvent& event)
{
if (!isEnabled())
return IGUIElement::OnEvent(event);
switch(event.EventType)
{
case EET_KEY_INPUT_EVENT:
if (event.KeyInput.PressedDown &&
(event.KeyInput.Key == KEY_RETURN || event.KeyInput.Key == KEY_SPACE))
{
if (!IsPushButton)
setPressed(true);
else
setPressed(!Pressed);
return true;
}
if (Pressed && !IsPushButton && event.KeyInput.PressedDown && event.KeyInput.Key == KEY_ESCAPE)
{
setPressed(false);
return true;
}
else
if (!event.KeyInput.PressedDown && Pressed &&
(event.KeyInput.Key == KEY_RETURN || event.KeyInput.Key == KEY_SPACE))
{
if (!IsPushButton)
setPressed(false);
if (Parent)
{
SEvent newEvent;
newEvent.EventType = EET_GUI_EVENT;
newEvent.GUIEvent.Caller = this;
newEvent.GUIEvent.Element = 0;
newEvent.GUIEvent.EventType = EGET_BUTTON_CLICKED;
Parent->OnEvent(newEvent);
}
return true;
}
break;
case EET_GUI_EVENT:
if (event.GUIEvent.EventType == EGET_ELEMENT_FOCUS_LOST)
{
if (event.GUIEvent.Caller == this && !IsPushButton)
setPressed(false);
}
break;
case EET_MOUSE_INPUT_EVENT:
if (event.MouseInput.Event == EMIE_LMOUSE_PRESSED_DOWN)
{
if (Environment->hasFocus(this) &&
!AbsoluteClippingRect.isPointInside(core::position2d<s32>(event.MouseInput.X, event.MouseInput.Y)))
{
Environment->removeFocus(this);
return false;
}
if (!IsPushButton)
setPressed(true);
Environment->setFocus(this);
return true;
}
else
if (event.MouseInput.Event == EMIE_LMOUSE_LEFT_UP)
{
bool wasPressed = Pressed;
if ( !AbsoluteClippingRect.isPointInside( core::position2d<s32>(event.MouseInput.X, event.MouseInput.Y ) ) )
{
if (!IsPushButton)
setPressed(false);
return true;
}
if (!IsPushButton)
setPressed(false);
else
{
setPressed(!Pressed);
}
if ((!IsPushButton && wasPressed && Parent) ||
(IsPushButton && wasPressed != Pressed))
{
SEvent newEvent;
newEvent.EventType = EET_GUI_EVENT;
newEvent.GUIEvent.Caller = this;
newEvent.GUIEvent.Element = 0;
newEvent.GUIEvent.EventType = EGET_BUTTON_CLICKED;
Parent->OnEvent(newEvent);
}
return true;
}
break;
default:
break;
}
return Parent ? Parent->OnEvent(event) : false;
}
void CGUIButton::draw()
{
if (!IsVisible)
return;
IGUISkin* skin = Environment->getSkin();
video::IVideoDriver* driver = Environment->getVideoDriver();
const core::position2di spritePos = AbsoluteRect.getCenter();
if (!Pressed)
{
if (DrawBorder)
skin->draw3DButtonPaneStandard(this, AbsoluteRect, &AbsoluteClippingRect);
if (Image)
{
core::position2d<s32> pos = spritePos;
pos.X -= ImageRect.getWidth() / 2;
pos.Y -= ImageRect.getHeight() / 2;
driver->draw2DImage(Image,
ScaleImage? AbsoluteRect :
core::recti(pos, ImageRect.getSize()),
ImageRect, &AbsoluteClippingRect,
0, UseAlphaChannel);
}
if (SpriteBank && ButtonSprites[EGBS_BUTTON_UP].Index != -1)
{
SpriteBank->draw2DSprite(ButtonSprites[EGBS_BUTTON_UP].Index, spritePos,
&AbsoluteClippingRect, ButtonSprites[EGBS_BUTTON_UP].Color, ClickTime, os::Timer::getTime(),
ButtonSprites[EGBS_BUTTON_UP].Loop, true);
}
}
else
{
if (DrawBorder)
skin->draw3DButtonPanePressed(this, AbsoluteRect, &AbsoluteClippingRect);
if (PressedImage)
{
core::position2d<s32> pos = spritePos;
pos.X -= PressedImageRect.getWidth() / 2;
pos.Y -= PressedImageRect.getHeight() / 2;
if (Image == PressedImage && PressedImageRect == ImageRect)
{
pos.X += 1;
pos.Y += 1;
}
driver->draw2DImage(PressedImage,
ScaleImage? AbsoluteRect :
core::recti(pos, PressedImageRect.getSize()),
PressedImageRect, &AbsoluteClippingRect,
0, UseAlphaChannel);
}
if (SpriteBank && ButtonSprites[EGBS_BUTTON_DOWN].Index != -1)
{
SpriteBank->draw2DSprite(ButtonSprites[EGBS_BUTTON_DOWN].Index, spritePos,
&AbsoluteClippingRect, ButtonSprites[EGBS_BUTTON_DOWN].Color, ClickTime, os::Timer::getTime(),
ButtonSprites[EGBS_BUTTON_DOWN].Loop, true);
}
}
if (Text.size())
{
IGUIFont* font = OverrideFont;
if (!OverrideFont)
font = skin->getFont(EGDF_BUTTON);
core::rect<s32> rect = AbsoluteRect;
if (Pressed)
rect.UpperLeftCorner.Y += 2;
if (font)
font->draw(Text.c_str(), rect,
skin->getColor(isEnabled() ? EGDC_BUTTON_TEXT : EGDC_GRAY_TEXT),
true, true, &AbsoluteClippingRect);
}
IGUIElement::draw();
}
void CGUIButton::setOverrideFont(IGUIFont* font)
{
if (OverrideFont == font)
return;
if (OverrideFont)
OverrideFont->drop();
OverrideFont = font;
if (OverrideFont)
OverrideFont->grab();
}
void CGUIButton::setImage(video::ITexture* image)
{
if (image)
image->grab();
if (Image)
Image->drop();
Image = image;
if (image)
ImageRect = core::rect<s32>(core::position2d<s32>(0,0), image->getOriginalSize());
if (!PressedImage)
setPressedImage(Image);
}
void CGUIButton::setImage(video::ITexture* image, const core::rect<s32>& pos)
{
setImage(image);
ImageRect = pos;
}
void CGUIButton::setPressedImage(video::ITexture* image)
{
if (image)
image->grab();
if (PressedImage)
PressedImage->drop();
PressedImage = image;
if (image)
PressedImageRect = core::rect<s32>(core::position2d<s32>(0,0), image->getOriginalSize());
}
void CGUIButton::setPressedImage(video::ITexture* image, const core::rect<s32>& pos)
{
setPressedImage(image);
PressedImageRect = pos;
}
void CGUIButton::setIsPushButton(bool isPushButton)
{
IsPushButton = isPushButton;
}
bool CGUIButton::isPressed() const
{
_IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX;
return Pressed;
}
void CGUIButton::setPressed(bool pressed)
{
if (Pressed != pressed)
{
ClickTime = os::Timer::getTime();
Pressed = pressed;
}
}
bool CGUIButton::isPushButton() const
{
_IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX;
return IsPushButton;
}
void CGUIButton::setUseAlphaChannel(bool useAlphaChannel)
{
UseAlphaChannel = useAlphaChannel;
}
bool CGUIButton::isAlphaChannelUsed() const
{
_IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX;
return UseAlphaChannel;
}
bool CGUIButton::isDrawingBorder() const
{
_IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX;
return DrawBorder;
}
void CGUIButton::serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options=0) const
{
IGUIButton::serializeAttributes(out,options);
out->addBool ("PushButton", IsPushButton );
if (IsPushButton)
out->addBool("Pressed", Pressed);
out->addTexture ("Image", Image);
out->addRect ("ImageRect", ImageRect);
out->addTexture ("PressedImage", PressedImage);
out->addRect ("PressedImageRect", PressedImageRect);
out->addBool ("UseAlphaChannel", isAlphaChannelUsed());
out->addBool ("Border", isDrawingBorder());
out->addBool ("ScaleImage", isScalingImage());
}
void CGUIButton::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options=0)
{
IGUIButton::deserializeAttributes(in,options);
IsPushButton = in->getAttributeAsBool("PushButton");
Pressed = IsPushButton ? in->getAttributeAsBool("Pressed") : false;
core::rect<s32> rec = in->getAttributeAsRect("ImageRect");
if (rec.isValid())
setImage( in->getAttributeAsTexture("Image"), rec);
else
setImage( in->getAttributeAsTexture("Image") );
rec = in->getAttributeAsRect("PressedImageRect");
if (rec.isValid())
setPressedImage( in->getAttributeAsTexture("PressedImage"), rec);
else
setPressedImage( in->getAttributeAsTexture("PressedImage") );
setDrawBorder(in->getAttributeAsBool("Border"));
setUseAlphaChannel(in->getAttributeAsBool("UseAlphaChannel"));
setScaleImage(in->getAttributeAsBool("ScaleImage"));
updateAbsolutePosition();
}
}
}
#endif