Retour
Version Originale

./aip/1.8aipmod/source/Irrlicht/CGUIMessageBox.cpp :


// Copyright (C) 2002-2011 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"
#ifdef _IRR_COMPILE_WITH_GUI_

#include "IGUISkin.h"
#include "IGUIEnvironment.h"
#include "IGUIButton.h"
#include "IGUIFont.h"
#include "ITexture.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, video::ITexture* image)
: CGUIWindow(environment, parent, id, rectangle),
	OkButton(0), CancelButton(0), YesButton(0), NoButton(0), StaticText(0),
	Icon(0), IconTexture(image),
	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);

	if ( IconTexture )
		IconTexture->grab();

	refreshControls();
}


//! destructor

CGUIMessageBox::~CGUIMessageBox()
{
	if (StaticText)
		StaticText->drop();

	if (OkButton)
		OkButton->drop();

	if (CancelButton)
		CancelButton->drop();

	if (YesButton)
		YesButton->drop();

	if (NoButton)
		NoButton->drop();

	if (Icon)
		Icon->drop();

	if ( IconTexture )
		IconTexture->drop();
}

void CGUIMessageBox::setButton(IGUIButton*& button, bool isAvailable, const core::rect<s32> & btnRect, const wchar_t * text, IGUIElement*& focusMe)
{
	// add/remove ok button

	if (isAvailable)
	{
		if (!button)
		{
			button = Environment->addButton(btnRect, this);
			button->setSubElement(true);
			button->grab();
		}
		else
			button->setRelativePosition(btnRect);

		button->setText(text);

		focusMe = button;
	}
	else if (button)
	{
		button->drop();
		button->remove();
		button =0;
	}
}

void CGUIMessageBox::refreshControls()
{
	// Layout can be seen as 4 boxes (a layoutmanager would be nice)

	// One box at top over the whole width for title

	// Two boxes with same height at the middle beside each other for icon and for text

	// One box at the bottom for the buttons


	const IGUISkin* skin = Environment->getSkin();

	const s32 buttonHeight   = skin->getSize(EGDS_BUTTON_HEIGHT);
	const s32 buttonWidth    = skin->getSize(EGDS_BUTTON_WIDTH);
	const s32 titleHeight    = skin->getSize(EGDS_WINDOW_BUTTON_WIDTH)+2;	// titlebar has no own constant

	const s32 buttonDistance = skin->getSize(EGDS_WINDOW_BUTTON_WIDTH);
	const s32 borderWidth 	 = skin->getSize(EGDS_MESSAGE_BOX_GAP_SPACE);

	// add the static text for the message

	core::rect<s32> staticRect;
	staticRect.UpperLeftCorner.X = borderWidth;
	staticRect.UpperLeftCorner.Y = titleHeight + borderWidth;
	staticRect.LowerRightCorner.X = staticRect.UpperLeftCorner.X + skin->getSize(EGDS_MESSAGE_BOX_MAX_TEXT_WIDTH);
	staticRect.LowerRightCorner.Y = staticRect.UpperLeftCorner.Y + skin->getSize(EGDS_MESSAGE_BOX_MAX_TEXT_HEIGHT);
	if (!StaticText)
	{
		StaticText = Environment->addStaticText(MessageText.c_str(), staticRect, false, false, this);

		StaticText->setWordWrap(true);
		StaticText->setSubElement(true);
		StaticText->grab();
	}
	else
	{
		StaticText->setRelativePosition(staticRect);
		StaticText->setText(MessageText.c_str());
	}

	s32 textHeight  = StaticText->getTextHeight();
	s32 textWidth = StaticText->getTextWidth() + 6;	// +6 because the static itself needs that

	const s32 iconHeight = IconTexture ? IconTexture->getOriginalSize().Height : 0;

	if ( textWidth < skin->getSize(EGDS_MESSAGE_BOX_MIN_TEXT_WIDTH) )
		textWidth = skin->getSize(EGDS_MESSAGE_BOX_MIN_TEXT_WIDTH) + 6;
	// no neeed to check for max because it couldn't get larger due to statictextbox.

	if ( textHeight < skin->getSize(EGDS_MESSAGE_BOX_MIN_TEXT_HEIGHT) )
		textHeight = skin->getSize(EGDS_MESSAGE_BOX_MIN_TEXT_HEIGHT);
	if ( textHeight > skin->getSize(EGDS_MESSAGE_BOX_MAX_TEXT_HEIGHT) )
		textHeight = skin->getSize(EGDS_MESSAGE_BOX_MAX_TEXT_HEIGHT);

	// content is text + icons + borders (but not titlebar)

	s32 contentHeight = textHeight > iconHeight ? textHeight : iconHeight;
	contentHeight += borderWidth;
	s32 contentWidth = 0;

	// add icon

	if ( IconTexture )
	{
		core::position2d<s32> iconPos;
		iconPos.Y = titleHeight + borderWidth;
		if ( iconHeight < textHeight )
			iconPos.Y += (textHeight-iconHeight) / 2;
		iconPos.X = borderWidth;

		if (!Icon)
		{
			Icon = Environment->addImage(IconTexture, iconPos, true, this);
			Icon->setSubElement(true);
			Icon->grab();
		}
		else
		{
			core::rect<s32> iconRect( iconPos.X, iconPos.Y, iconPos.X + IconTexture->getOriginalSize().Width, iconPos.Y + IconTexture->getOriginalSize().Height );
			Icon->setRelativePosition(iconRect);
		}

		contentWidth += borderWidth + IconTexture->getOriginalSize().Width;
	}
	else if ( Icon )
	{
		Icon->drop();
		Icon->remove();
		Icon = 0;
	}

	// position text

	core::rect<s32> textRect;
	textRect.UpperLeftCorner.X = contentWidth + borderWidth;
	textRect.UpperLeftCorner.Y = titleHeight + borderWidth;
	if ( textHeight < iconHeight )
		textRect.UpperLeftCorner.Y += (iconHeight-textHeight) / 2;
	textRect.LowerRightCorner.X = textRect.UpperLeftCorner.X + textWidth;
	textRect.LowerRightCorner.Y = textRect.UpperLeftCorner.Y + textHeight;
	contentWidth += 2*borderWidth + textWidth;
	StaticText->setRelativePosition( textRect );

	// find out button size needs

	s32 countButtons = 0;
	if (Flags & EMBF_OK)
		++countButtons;
	if (Flags & EMBF_CANCEL)
		++countButtons;
	if (Flags & EMBF_YES)
		++countButtons;
	if (Flags & EMBF_NO)
		++countButtons;

	s32 buttonBoxWidth = countButtons * buttonWidth + 2 * borderWidth;
	if ( countButtons > 1 )
		buttonBoxWidth += (countButtons-1) * buttonDistance;
	s32 buttonBoxHeight = buttonHeight + 2 * borderWidth;

	// calc new message box sizes

	core::rect<s32> tmp = getRelativePosition();
	s32 msgBoxHeight = titleHeight + contentHeight + buttonBoxHeight;
	s32 msgBoxWidth = contentWidth > buttonBoxWidth ? contentWidth : buttonBoxWidth;

	// adjust message box position

	tmp.UpperLeftCorner.Y = (Parent->getAbsolutePosition().getHeight() - msgBoxHeight) / 2;
	tmp.LowerRightCorner.Y = tmp.UpperLeftCorner.Y + msgBoxHeight;
	tmp.UpperLeftCorner.X = (Parent->getAbsolutePosition().getWidth() - msgBoxWidth) / 2;
	tmp.LowerRightCorner.X = tmp.UpperLeftCorner.X + msgBoxWidth;
	setRelativePosition(tmp);

	// add buttons


	core::rect<s32> btnRect;
	btnRect.UpperLeftCorner.Y = titleHeight + contentHeight + borderWidth;
	btnRect.LowerRightCorner.Y = btnRect.UpperLeftCorner.Y + buttonHeight;
	btnRect.UpperLeftCorner.X = borderWidth;
	if ( contentWidth > buttonBoxWidth )
		btnRect.UpperLeftCorner.X += (contentWidth - buttonBoxWidth) / 2;	// center buttons

	btnRect.LowerRightCorner.X = btnRect.UpperLeftCorner.X + buttonWidth;

	IGUIElement* focusMe = 0;
	setButton(OkButton, (Flags & EMBF_OK) != 0, btnRect, skin->getDefaultText(EGDT_MSG_BOX_OK), focusMe);
	if ( Flags & EMBF_OK )
		btnRect += core::position2d<s32>(buttonWidth + buttonDistance, 0);
	setButton(CancelButton, (Flags & EMBF_CANCEL) != 0, btnRect, skin->getDefaultText(EGDT_MSG_BOX_CANCEL), focusMe);
	if ( Flags & EMBF_CANCEL )
		btnRect += core::position2d<s32>(buttonWidth + buttonDistance, 0);
	setButton(YesButton, (Flags & EMBF_YES) != 0, btnRect, skin->getDefaultText(EGDT_MSG_BOX_YES), focusMe);
	if ( Flags & EMBF_YES )
		btnRect += core::position2d<s32>(buttonWidth + buttonDistance, 0);
	setButton(NoButton, (Flags & EMBF_NO) != 0, btnRect, skin->getDefaultText(EGDT_MSG_BOX_NO), focusMe);

	if (Environment->hasFocus(this) && focusMe)
		Environment->setFocus(focusMe);
}


//! called if an event happened.

bool CGUIMessageBox::OnEvent(const SEvent& event)
{
	if (isEnabled())
	{
		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) YesButton->setPressed(false);
						if (NoButton) NoButton->setPressed(false);
						Pressed = false;
					}
					else
					if (CancelButton)
					{
						CancelButton->setPressed(true);
						Pressed = true;
					}
					else
					if (CloseButton && CloseButton->isVisible())
					{
						CloseButton->setPressed(true);
						Pressed = true;
					}
					break;
				default: // no other key is handled here

					break;
				}
			}
			else
			if (Pressed)
			{
				if (OkButton && event.KeyInput.Key == KEY_RETURN)
				{
					setVisible(false);	// this is a workaround to make sure it's no longer the hovered element, crashes on pressing 1-2 times ESC

					Environment->setFocus(0);
					outevent.GUIEvent.EventType = EGET_MESSAGEBOX_OK;
					Parent->OnEvent(outevent);
					remove();
					return true;
				}
				else
				if ((CancelButton || CloseButton) && event.KeyInput.Key == KEY_ESCAPE)
				{
					setVisible(false);	// this is a workaround to make sure it's no longer the hovered element, crashes on pressing 1-2 times ESC

					Environment->setFocus(0);
					outevent.GUIEvent.EventType = EGET_MESSAGEBOX_CANCEL;
					Parent->OnEvent(outevent);
					remove();
					return true;
				}
				else
				if (YesButton && event.KeyInput.Key == KEY_KEY_Y)
				{
					setVisible(false);	// this is a workaround to make sure it's no longer the hovered element, crashes on pressing 1-2 times ESC

					Environment->setFocus(0);
					outevent.GUIEvent.EventType = EGET_MESSAGEBOX_YES;
					Parent->OnEvent(outevent);
					remove();
					return true;
				}
				else
				if (NoButton && event.KeyInput.Key == KEY_KEY_N)
				{
					setVisible(false);	// this is a workaround to make sure it's no longer the hovered element, crashes on pressing 1-2 times ESC

					Environment->setFocus(0);
					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)
				{
					setVisible(false);	// this is a workaround to make sure it's no longer the hovered element, crashes on pressing 1-2 times ESC

					Environment->setFocus(0);
					outevent.GUIEvent.EventType = EGET_MESSAGEBOX_OK;
					Parent->OnEvent(outevent);
					remove();
					return true;
				}
				else
				if (event.GUIEvent.Caller == CancelButton ||
					event.GUIEvent.Caller == CloseButton)
				{
					setVisible(false);	// this is a workaround to make sure it's no longer the hovered element, crashes on pressing 1-2 times ESC

					Environment->setFocus(0);
					outevent.GUIEvent.EventType = EGET_MESSAGEBOX_CANCEL;
					Parent->OnEvent(outevent);
					remove();
					return true;
				}
				else
				if (event.GUIEvent.Caller == YesButton)
				{
					setVisible(false);	// this is a workaround to make sure it's no longer the hovered element, crashes on pressing 1-2 times ESC

					Environment->setFocus(0);
					outevent.GUIEvent.EventType = EGET_MESSAGEBOX_YES;
					Parent->OnEvent(outevent);
					remove();
					return true;
				}
				else
				if (event.GUIEvent.Caller == NoButton)
				{
					setVisible(false);	// this is a workaround to make sure it's no longer the hovered element, crashes on pressing 1-2 times ESC

					Environment->setFocus(0);
					outevent.GUIEvent.EventType = EGET_MESSAGEBOX_NO;
					Parent->OnEvent(outevent);
					remove();
					return true;
				}
			}
			break;
		default:
			break;
		}
	}

	return CGUIWindow::OnEvent(event);
}


//! Writes attributes of the element.

void CGUIMessageBox::serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options=0) const
{
	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->addTexture	("Texture",			IconTexture);

	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;

	if ( IconTexture )
	{
		IconTexture->drop();
		IconTexture = NULL;
	}
	IconTexture = in->getAttributeAsTexture("Texture");
	if ( IconTexture )
		IconTexture->grab();

	MessageText = in->getAttributeAsStringW("MessageText").c_str();

	CGUIWindow::deserializeAttributes(in,options);

	refreshControls();
}


} // end namespace gui

} // end namespace irr


#endif // _IRR_COMPILE_WITH_GUI_


Options Liens officiels Caractéristiques Statistiques Communauté
Corrections
irrlicht
irrklang
irredit
irrxml
xhtml 1.0
css 2.1
Propulsé par FluxBB
Traduit par FluxBB.fr
881 membres
1426 sujets
11116 messages
Dernier membre inscrit: Bidule
16 invités en ligne
Aucun membre connecté
RSS Feed