irrlicht/source/Irrlicht/CGUIMessageBox.cpp
bitplane e0a66f229b Added navigation through the GUI using tab and the shift and control keys. Added keyboard navigation for most elements. Fixed that annoying bug where you had to click twice to change focus.
Added IGUIElement::isMyChild, isPointInside,  SEvent.GUIEvent.Element. 
Changed setFocus and removeFocus to return bools.
changed quaternion::toAngleAxis to use iszero. 

git-svn-id: http://svn.code.sf.net/p/irrlicht/code/trunk@763 dfc29bdd-3216-0410-991c-e03cc46cb475
2007-07-07 07:03:54 +00:00

421 lines
9.9 KiB
C++

// Copyright (C) 2002-2007 Nikolaus Gebhardt
// This file is part of the "Irrlicht Engine".
// For conditions of distribution and use, see copyright notice in irrlicht.h
#include "CGUIMessageBox.h"
#include "IGUISkin.h"
#include "IGUIEnvironment.h"
#include "IGUIButton.h"
#include "IGUIFont.h"
namespace irr
{
namespace gui
{
//! constructor
CGUIMessageBox::CGUIMessageBox(IGUIEnvironment* environment, const wchar_t* caption,
const wchar_t* text, s32 flags,
IGUIElement* parent, s32 id, core::rect<s32> rectangle)
: CGUIWindow(environment, parent, id, rectangle),
OkButton(0), CancelButton(0), YesButton(0), NoButton(0), StaticText(0),
Flags(flags), MessageText(text), Pressed(false)
{
#ifdef _DEBUG
setDebugName("CGUIMessageBox");
#endif
// set element type
Type = EGUIET_MESSAGE_BOX;
// remove focus
Environment->setFocus(0);
// remove buttons
getMaximizeButton()->remove();
getMinimizeButton()->remove();
if (caption)
setText(caption);
Environment->setFocus(this);
refreshControls();
}
void CGUIMessageBox::refreshControls()
{
IGUISkin* skin = Environment->getSkin();
IGUIElement* focusMe = 0;
s32 buttonHeight = skin->getSize(EGDS_BUTTON_HEIGHT);
s32 buttonWidth = skin->getSize(EGDS_BUTTON_WIDTH);
s32 titleHeight = skin->getSize(EGDS_WINDOW_BUTTON_WIDTH)+2;
s32 buttonDistance = skin->getSize(EGDS_WINDOW_BUTTON_WIDTH);
// add static multiline text
core::dimension2d<s32> dim(AbsoluteClippingRect.getWidth() - buttonWidth,
AbsoluteClippingRect.getHeight() - (buttonHeight * 3));
core::position2d<s32> pos((AbsoluteClippingRect.getWidth() - dim.Width) / 2,
buttonHeight / 2 + titleHeight);
if (!StaticText)
{
StaticText = Environment->addStaticText(MessageText.c_str(),
core::rect<s32>(pos, dim), false, false, this);
StaticText->setWordWrap(true);
StaticText->setSubElement(true);
StaticText->grab();
}
else
{
StaticText->setRelativePosition( core::rect<s32>(pos, dim));
StaticText->setText(MessageText.c_str());
}
// adjust static text height
s32 textHeight = StaticText->getTextHeight();
core::rect<s32> tmp = StaticText->getRelativePosition();
tmp.LowerRightCorner.Y = tmp.UpperLeftCorner.Y + textHeight;
StaticText->setRelativePosition(tmp);
dim.Height = textHeight;
// adjust message box height
tmp = getRelativePosition();
s32 msgBoxHeight = textHeight + (s32)(2.5f * buttonHeight) + titleHeight;
// adjust message box position
tmp.UpperLeftCorner.Y = (Parent->getAbsolutePosition().getHeight() - msgBoxHeight) / 2;
tmp.LowerRightCorner.Y = tmp.UpperLeftCorner.Y + msgBoxHeight;
setRelativePosition(tmp);
// add buttons
s32 countButtons = 0;
if (Flags & EMBF_OK) ++countButtons;
if (Flags & EMBF_CANCEL) ++countButtons;
if (Flags & EMBF_YES) ++countButtons;
if (Flags & EMBF_NO) ++countButtons;
core::rect<s32> btnRect;
btnRect.UpperLeftCorner.Y = pos.Y + dim.Height + buttonHeight / 2;
btnRect.LowerRightCorner.Y = btnRect.UpperLeftCorner.Y + buttonHeight;
btnRect.UpperLeftCorner.X = (AbsoluteClippingRect.getWidth() -
((buttonWidth + buttonDistance)*countButtons)) / 2;
btnRect.LowerRightCorner.X = btnRect.UpperLeftCorner.X + buttonWidth;
// add/remove ok button
if (Flags & EMBF_OK)
{
if (!OkButton)
{
OkButton = Environment->addButton(btnRect, this);
OkButton->setSubElement(true);
OkButton->grab();
}
else
OkButton->setRelativePosition(btnRect);
OkButton->setText(skin->getDefaultText(EGDT_MSG_BOX_OK));
btnRect.LowerRightCorner.X += buttonWidth + buttonDistance;
btnRect.UpperLeftCorner.X += buttonWidth + buttonDistance;
focusMe = OkButton;
}
else if (OkButton)
{
OkButton->drop();
OkButton->remove();
OkButton =0;
}
// add cancel button
if (Flags & EMBF_CANCEL)
{
if (!CancelButton)
{
CancelButton = Environment->addButton(btnRect, this);
CancelButton->setSubElement(true);
CancelButton->grab();
}
else
CancelButton->setRelativePosition(btnRect);
CancelButton->setText(skin->getDefaultText(EGDT_MSG_BOX_CANCEL));
CancelButton->grab();
btnRect.LowerRightCorner.X += buttonWidth + buttonDistance;
btnRect.UpperLeftCorner.X += buttonWidth + buttonDistance;
if (!focusMe)
focusMe = CancelButton;
}
else if (CancelButton)
{
CancelButton->drop();
CancelButton->remove();
CancelButton = 0;
}
// add/remove yes button
if (Flags & EMBF_YES)
{
if (!YesButton)
{
YesButton = Environment->addButton(btnRect, this);
YesButton->setSubElement(true);
YesButton->grab();
}
else
YesButton->setRelativePosition(btnRect);
YesButton->setText(skin->getDefaultText(EGDT_MSG_BOX_YES));
btnRect.LowerRightCorner.X += buttonWidth + buttonDistance;
btnRect.UpperLeftCorner.X += buttonWidth + buttonDistance;
if (!focusMe)
focusMe = YesButton;
}
else if (YesButton)
{
YesButton->drop();
YesButton->remove();
YesButton = 0;
}
// add no button
if (Flags & EMBF_NO)
{
if (!NoButton)
{
NoButton = Environment->addButton(btnRect, this);
NoButton->setSubElement(true);
NoButton->grab();
}
else
NoButton->setRelativePosition(btnRect);
NoButton->setText(skin->getDefaultText(EGDT_MSG_BOX_NO));
btnRect.LowerRightCorner.X += buttonWidth + buttonDistance;
btnRect.UpperLeftCorner.X += buttonWidth + buttonDistance;
if (!focusMe)
focusMe = NoButton;
}
else if (NoButton)
{
NoButton->drop();
NoButton->remove();
NoButton = 0;
}
if (Environment->hasFocus(this) && focusMe)
Environment->setFocus(focusMe);
}
//! destructor
CGUIMessageBox::~CGUIMessageBox()
{
if (StaticText)
StaticText->drop();
if (OkButton)
OkButton->drop();
if (CancelButton)
CancelButton->drop();
if (YesButton)
YesButton->drop();
if (NoButton)
NoButton->drop();
}
//! called if an event happened.
bool CGUIMessageBox::OnEvent(SEvent event)
{
SEvent outevent;
outevent.EventType = EET_GUI_EVENT;
outevent.GUIEvent.Caller = this;
outevent.GUIEvent.Element = 0;
switch(event.EventType)
{
case EET_KEY_INPUT_EVENT:
if (event.KeyInput.PressedDown)
{
switch (event.KeyInput.Key)
{
case KEY_RETURN:
if (OkButton)
{
OkButton->setPressed(true);
Pressed = true;
}
break;
case KEY_KEY_Y:
if (YesButton)
{
YesButton->setPressed(true);
Pressed = true;
}
break;
case KEY_KEY_N:
if (NoButton)
{
NoButton->setPressed(true);
Pressed = true;
}
break;
case KEY_ESCAPE:
if (Pressed)
{
// cancel press
if (OkButton) OkButton->setPressed(false);
if (YesButton) OkButton->setPressed(false);
if (NoButton) OkButton->setPressed(false);
Pressed = false;
}
else
if (CancelButton)
{
CancelButton->setPressed(true);
Pressed = true;
}
else
if (CloseButton && CloseButton->isVisible())
{
CloseButton->setPressed(true);
Pressed = true;
}
}
}
else
if (Pressed)
{
if (OkButton && event.KeyInput.Key == KEY_RETURN)
{
outevent.GUIEvent.EventType = EGET_MESSAGEBOX_OK;
Parent->OnEvent(outevent);
remove();
return true;
}
else
if ((CancelButton || CloseButton) && event.KeyInput.Key == KEY_ESCAPE)
{
outevent.GUIEvent.EventType = EGET_MESSAGEBOX_CANCEL;
Parent->OnEvent(outevent);
remove();
return true;
}
else
if (YesButton && event.KeyInput.Key == KEY_KEY_Y)
{
outevent.GUIEvent.EventType = EGET_MESSAGEBOX_YES;
Parent->OnEvent(outevent);
remove();
return true;
}
else
if (NoButton && event.KeyInput.Key == KEY_KEY_N)
{
outevent.GUIEvent.EventType = EGET_MESSAGEBOX_NO;
Parent->OnEvent(outevent);
remove();
return true;
}
}
break;
case EET_GUI_EVENT:
if (event.GUIEvent.EventType == EGET_BUTTON_CLICKED)
{
if (event.GUIEvent.Caller == OkButton)
{
outevent.GUIEvent.EventType = EGET_MESSAGEBOX_OK;
Parent->OnEvent(outevent);
remove();
return true;
}
else
if (event.GUIEvent.Caller == CancelButton ||
event.GUIEvent.Caller == CloseButton)
{
outevent.GUIEvent.EventType = EGET_MESSAGEBOX_CANCEL;
Parent->OnEvent(outevent);
remove();
return true;
}
else
if (event.GUIEvent.Caller == YesButton)
{
outevent.GUIEvent.EventType = EGET_MESSAGEBOX_YES;
Parent->OnEvent(outevent);
remove();
return true;
}
else
if (event.GUIEvent.Caller == NoButton)
{
outevent.GUIEvent.EventType = EGET_MESSAGEBOX_NO;
Parent->OnEvent(outevent);
remove();
return true;
}
}
break;
}
return CGUIWindow::OnEvent(event);
}
//! Writes attributes of the element.
void CGUIMessageBox::serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options=0)
{
CGUIWindow::serializeAttributes(out,options);
out->addBool ("OkayButton", (Flags & EMBF_OK) != 0 );
out->addBool ("CancelButton", (Flags & EMBF_CANCEL)!= 0 );
out->addBool ("YesButton", (Flags & EMBF_YES) != 0 );
out->addBool ("NoButton", (Flags & EMBF_NO) != 0 );
out->addString ("MessageText", MessageText.c_str() );
}
//! Reads attributes of the element
void CGUIMessageBox::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options=0)
{
Flags = 0;
Flags = in->getAttributeAsBool("OkayButton") ? EMBF_OK : 0;
Flags |= in->getAttributeAsBool("CancelButton")? EMBF_CANCEL : 0;
Flags |= in->getAttributeAsBool("YesButton") ? EMBF_YES : 0;
Flags |= in->getAttributeAsBool("NoButton") ? EMBF_NO : 0;
MessageText = in->getAttributeAsStringW("MessageText").c_str();
CGUIWindow::deserializeAttributes(in,options);
refreshControls();
}
} // end namespace gui
} // end namespace irr