MessageBox supports now automatic resizing and images.

Deprecated EGDS_MESSAGE_BOX_WIDTH and EGDS_MESSAGE_BOX_HEIGHT.


git-svn-id: svn://svn.code.sf.net/p/irrlicht/code/trunk@2710 dfc29bdd-3216-0410-991c-e03cc46cb475
master
cutealien 2009-10-14 13:28:20 +00:00
parent a897201597
commit 1818454023
7 changed files with 187 additions and 150 deletions

View File

@ -240,11 +240,12 @@ public:
to (EMBF_OK | EMBF_CANCEL).
\param parent Parent gui element of the message box.
\param id Id with which the gui element can be identified.
\param image Optional texture which will be displayed beside the text as an image
\return Pointer to the created message box. Returns 0 if an error
occured. This pointer should not be dropped. See
IReferenceCounted::drop() for more information. */
virtual IGUIWindow* addMessageBox(const wchar_t* caption, const wchar_t* text=0,
bool modal = true, s32 flags = EMBF_OK, IGUIElement* parent=0, s32 id=-1) = 0;
bool modal = true, s32 flags = EMBF_OK, IGUIElement* parent=0, s32 id=-1, video::ITexture* image=0) = 0;
//! Adds a scrollbar.
/** \param horizontal Specifies if the scroll bar is drawn horizontal

View File

@ -139,9 +139,9 @@ namespace gui
EGDS_WINDOW_BUTTON_WIDTH,
//! width of a checkbox check
EGDS_CHECK_BOX_WIDTH,
//! width of a messagebox
//! deprecated
EGDS_MESSAGE_BOX_WIDTH,
//! height of a messagebox
//! deprecated
EGDS_MESSAGE_BOX_HEIGHT,
//! width of a default button
EGDS_BUTTON_WIDTH,
@ -155,6 +155,17 @@ namespace gui
EGDS_TITLEBARTEXT_DISTANCE_X,
//! distance for text in the title bar, from the top of the window rect
EGDS_TITLEBARTEXT_DISTANCE_Y,
//! free space in a messagebox between borders and contents on all sides
EGDS_MESSAGE_BOX_GAP_SPACE,
//! minimal space to reserve for messagebox text-width
EGDS_MESSAGE_BOX_MIN_TEXT_WIDTH,
//! maximal space to reserve for messagebox text-width
EGDS_MESSAGE_BOX_MAX_TEST_WIDTH,
//! minimal space to reserve for messagebox text-height
EGDS_MESSAGE_BOX_MIN_TEXT_HEIGHT,
//! maximal space to reserve for messagebox text-height
EGDS_MESSAGE_BOX_MAX_TEXT_HEIGHT,
//! this value is not used, it only specifies the amount of default sizes
//! available.
EGDS_COUNT
@ -174,6 +185,13 @@ namespace gui
"ButtonHeight",
"TextDistanceX",
"TextDistanceY",
"TitleBarTextX",
"TitleBarTextY",
"MessageBoxGapSpace",
"MessageBoxMinTextWidth",
"MessageBoxMaxTextWidth",
"MessageBoxMinTextHeight",
"MessageBoxMaxTextHeight",
0,
};

View File

@ -978,7 +978,7 @@ IGUIElement* CGUIEnvironment::addModalScreen(IGUIElement* parent)
//! Adds a message box.
IGUIWindow* CGUIEnvironment::addMessageBox(const wchar_t* caption, const wchar_t* text,
bool modal, s32 flag, IGUIElement* parent, s32 id)
bool modal, s32 flag, IGUIElement* parent, s32 id, video::ITexture* image)
{
if (!CurrentSkin)
return 0;
@ -990,8 +990,8 @@ IGUIWindow* CGUIEnvironment::addMessageBox(const wchar_t* caption, const wchar_t
screenDim.Width = parent->getAbsolutePosition().getWidth();
screenDim.Height = parent->getAbsolutePosition().getHeight();
msgBoxDim.Width = CurrentSkin->getSize(gui::EGDS_MESSAGE_BOX_WIDTH);
msgBoxDim.Height = CurrentSkin->getSize(gui::EGDS_MESSAGE_BOX_HEIGHT);
msgBoxDim.Width = 2;
msgBoxDim.Height = 2;
rect.UpperLeftCorner.X = (screenDim.Width - msgBoxDim.Width) / 2;
rect.UpperLeftCorner.Y = (screenDim.Height - msgBoxDim.Height) / 2;
@ -1005,7 +1005,7 @@ IGUIWindow* CGUIEnvironment::addMessageBox(const wchar_t* caption, const wchar_t
}
IGUIWindow* win = new CGUIMessageBox(this, caption, text, flag,
parent, id, rect);
parent, id, rect, image);
win->drop();
return win;

View File

@ -96,7 +96,7 @@ public:
//! Adds a message box.
virtual IGUIWindow* addMessageBox(const wchar_t* caption, const wchar_t* text=0,
bool modal = true, s32 flag = EMBF_OK, IGUIElement* parent=0, s32 id=-1);
bool modal = true, s32 flag = EMBF_OK, IGUIElement* parent=0, s32 id=-1, video::ITexture* image=0);
//! adds a scrollbar. The returned pointer must not be dropped.
virtual IGUIScrollBar* addScrollBar(bool horizontal, const core::rect<s32>& rectangle,

View File

@ -9,6 +9,7 @@
#include "IGUIEnvironment.h"
#include "IGUIButton.h"
#include "IGUIFont.h"
#include "ITexture.h"
namespace irr
{
@ -18,9 +19,10 @@ 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)
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
@ -43,6 +45,9 @@ CGUIMessageBox::CGUIMessageBox(IGUIEnvironment* environment, const wchar_t* capt
Environment->setFocus(this);
if ( IconTexture )
IconTexture->grab();
refreshControls();
}
@ -64,62 +69,134 @@ CGUIMessageBox::~CGUIMessageBox()
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();
IGUIElement* focusMe = 0;
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;
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 static multiline text
core::dimension2d<s32> dim(AbsoluteClippingRect.getWidth() - buttonWidth,
AbsoluteClippingRect.getHeight() - (buttonHeight * 2));
const core::position2d<s32> pos((AbsoluteClippingRect.getWidth() - dim.Width) / 2,
buttonHeight / 2 + titleHeight);
// 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_TEST_WIDTH);
staticRect.LowerRightCorner.Y = staticRect.UpperLeftCorner.Y + skin->getSize(EGDS_MESSAGE_BOX_MAX_TEXT_HEIGHT);
if (!StaticText)
{
StaticText = Environment->addStaticText(MessageText.c_str(),
core::rect<s32>(pos, dim), false, false, this);
StaticText = Environment->addStaticText(MessageText.c_str(), staticRect, false, false, this);
StaticText->setWordWrap(true);
StaticText->setSubElement(true);
StaticText->grab();
}
else
{
StaticText->setRelativePosition(core::rect<s32>(pos, dim));
StaticText->setRelativePosition(staticRect);
StaticText->setText(MessageText.c_str());
}
// adjust static text height
s32 textHeight = StaticText->getTextHeight();
s32 textWidth = StaticText->getTextWidth() + 6; // +6 because the static itself needs that
const s32 iconHeight = IconTexture ? IconTexture->getOriginalSize().Height : 0;
const s32 textHeight = StaticText->getTextHeight();
core::rect<s32> tmp = StaticText->getRelativePosition();
tmp.LowerRightCorner.Y = tmp.UpperLeftCorner.Y + textHeight;
StaticText->setRelativePosition(tmp);
dim.Height = dim.Height - buttonHeight < tmp.getHeight() ? tmp.getHeight() : dim.Height - buttonHeight;
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);
// adjust message box height if required
// content is text + icons + borders (but not titlebar)
s32 contentHeight = textHeight > iconHeight ? textHeight : iconHeight;
contentHeight += borderWidth;
s32 contentWidth = 0;
tmp = getRelativePosition();
s32 msgBoxHeight = textHeight + core::floor32(2.5f * buttonHeight) + titleHeight;
msgBoxHeight = tmp.getHeight() < msgBoxHeight ? msgBoxHeight : tmp.getHeight();
// add icon
if ( IconTexture )
{
core::position2d<s32> iconPos;
iconPos.Y = titleHeight + borderWidth;
if ( iconHeight < textHeight )
iconPos.Y += (textHeight-iconHeight) / 2;
iconPos.X = borderWidth;
// adjust message box position
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);
}
tmp.UpperLeftCorner.Y = (Parent->getAbsolutePosition().getHeight() - msgBoxHeight) / 2;
tmp.LowerRightCorner.Y = tmp.UpperLeftCorner.Y + msgBoxHeight;
setRelativePosition(tmp);
contentWidth += borderWidth + IconTexture->getOriginalSize().Width;
}
else if ( Icon )
{
Icon->drop();
Icon->remove();
Icon = 0;
}
// add buttons
// 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;
@ -130,123 +207,44 @@ void CGUIMessageBox::refreshControls()
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 = pos.Y + dim.Height + buttonHeight / 2;
btnRect.UpperLeftCorner.Y = titleHeight + contentHeight + borderWidth;
btnRect.LowerRightCorner.Y = btnRect.UpperLeftCorner.Y + buttonHeight;
btnRect.UpperLeftCorner.X = (AbsoluteClippingRect.getWidth() -
(buttonWidth*countButtons + (buttonDistance*countButtons+1))) / 2 +
buttonDistance / 2;
btnRect.UpperLeftCorner.X = borderWidth;
if ( contentWidth > buttonBoxWidth )
btnRect.UpperLeftCorner.X += (contentWidth - buttonBoxWidth) / 2; // center buttons
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));
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;
}
IGUIElement* focusMe = 0;
setButton(OkButton, Flags & EMBF_OK, btnRect, skin->getDefaultText(EGDT_MSG_BOX_OK), focusMe);
if ( Flags & EMBF_OK )
btnRect += core::position2d<s32>(buttonWidth + buttonDistance, 0);
setButton(CancelButton, Flags & EMBF_CANCEL, btnRect, skin->getDefaultText(EGDT_MSG_BOX_CANCEL), focusMe);
if ( Flags & EMBF_CANCEL )
btnRect += core::position2d<s32>(buttonWidth + buttonDistance, 0);
setButton(YesButton, Flags & EMBF_YES, btnRect, skin->getDefaultText(EGDT_MSG_BOX_YES), focusMe);
if ( Flags & EMBF_YES )
btnRect += core::position2d<s32>(buttonWidth + buttonDistance, 0);
setButton(NoButton, Flags & EMBF_NO, btnRect, skin->getDefaultText(EGDT_MSG_BOX_NO), focusMe);
if (Environment->hasFocus(this) && focusMe)
Environment->setFocus(focusMe);
@ -409,6 +407,7 @@ void CGUIMessageBox::serializeAttributes(io::IAttributes* out, io::SAttributeRea
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());
}
@ -424,6 +423,15 @@ void CGUIMessageBox::deserializeAttributes(io::IAttributes* in, io::SAttributeRe
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);

View File

@ -10,6 +10,7 @@
#include "CGUIWindow.h"
#include "IGUIStaticText.h"
#include "IGUIImage.h"
#include "irrArray.h"
namespace irr
@ -23,7 +24,7 @@ namespace gui
//! constructor
CGUIMessageBox(IGUIEnvironment* environment, const wchar_t* caption,
const wchar_t* text, s32 flag,
IGUIElement* parent, s32 id, core::rect<s32> rectangle);
IGUIElement* parent, s32 id, core::rect<s32> rectangle, video::ITexture* image=0);
//! destructor
virtual ~CGUIMessageBox();
@ -40,12 +41,15 @@ namespace gui
private:
void refreshControls();
void setButton(IGUIButton*& button, bool isAvailable, const core::rect<s32> & btnRect, const wchar_t * text, IGUIElement*& focusMe);
IGUIButton* OkButton;
IGUIButton* CancelButton;
IGUIButton* YesButton;
IGUIButton* NoButton;
IGUIStaticText* StaticText;
IGUIImage * Icon;
video::ITexture * IconTexture;
s32 Flags;
core::stringw MessageText;

View File

@ -104,6 +104,12 @@ CGUISkin::CGUISkin(EGUI_SKIN_TYPE type, video::IVideoDriver* driver)
Sizes[EGDS_TITLEBARTEXT_DISTANCE_Y] = 2;
}
Sizes[EGDS_MESSAGE_BOX_GAP_SPACE] = 15;
Sizes[EGDS_MESSAGE_BOX_MIN_TEXT_WIDTH] = 0;
Sizes[EGDS_MESSAGE_BOX_MAX_TEST_WIDTH] = 500;
Sizes[EGDS_MESSAGE_BOX_MIN_TEXT_HEIGHT] = 0;
Sizes[EGDS_MESSAGE_BOX_MAX_TEXT_HEIGHT] = 99999;
Texts[EGDT_MSG_BOX_OK] = L"OK";
Texts[EGDT_MSG_BOX_CANCEL] = L"Cancel";
Texts[EGDT_MSG_BOX_YES] = L"Yes";