Commit 18184540 authored by cutealien's avatar cutealien

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
parent a8972015
......@@ -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
......
......@@ -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,
};
......
......@@ -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;
......
......@@ -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,
......
......@@ -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,189 +69,182 @@ 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);
// 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);
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_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
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;
// adjust message box height if required
tmp = getRelativePosition();
s32 msgBoxHeight = textHeight + core::floor32(2.5f * buttonHeight) + titleHeight;
msgBoxHeight = tmp.getHeight() < msgBoxHeight ? msgBoxHeight : tmp.getHeight();
// 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*countButtons + (buttonDistance*countButtons+1))) / 2 +
buttonDistance / 2;
btnRect.LowerRightCorner.X = btnRect.UpperLeftCorner.X + buttonWidth;
// add/remove ok button
if (Flags & EMBF_OK)
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 )
{
if (!OkButton)
core::position2d<s32> iconPos;
iconPos.Y = titleHeight + borderWidth;
if ( iconHeight < textHeight )
iconPos.Y += (textHeight-iconHeight) / 2;
iconPos.X = borderWidth;
if (!Icon)
{
OkButton = Environment->addButton(btnRect, this);
OkButton->setSubElement(true);
OkButton->grab();
Icon = Environment->addImage(IconTexture, iconPos, true, this);
Icon->setSubElement(true);
Icon->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();
core::rect<s32> iconRect( iconPos.X, iconPos.Y, iconPos.X + IconTexture->getOriginalSize().Width, iconPos.Y + IconTexture->getOriginalSize().Height );
Icon->setRelativePosition(iconRect);
}
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;
contentWidth += borderWidth + IconTexture->getOriginalSize().Width;
}
else if (CancelButton)
else if ( Icon )
{
CancelButton->drop();
CancelButton->remove();
CancelButton = 0;
Icon->drop();
Icon->remove();
Icon = 0;
}
// add/remove yes button
// 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)
{
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;
++countButtons;
if (Flags & EMBF_NO)
++countButtons;
if (!focusMe)
focusMe = YesButton;
}
else if (YesButton)
{
YesButton->drop();
YesButton->remove();
YesButton = 0;
}
s32 buttonBoxWidth = countButtons * buttonWidth + 2 * borderWidth;
if ( countButtons > 1 )
buttonBoxWidth += (countButtons-1) * buttonDistance;
s32 buttonBoxHeight = buttonHeight + 2 * borderWidth;
// add no button
if (Flags & EMBF_NO)
{
if (!NoButton)
{
NoButton = Environment->addButton(btnRect, this);
NoButton->setSubElement(true);
NoButton->grab();
}
else
NoButton->setRelativePosition(btnRect);
// calc new message box sizes
core::rect<s32> tmp = getRelativePosition();
s32 msgBoxHeight = titleHeight + contentHeight + buttonBoxHeight;
s32 msgBoxWidth = contentWidth > buttonBoxWidth ? contentWidth : buttonBoxWidth;
NoButton->setText(skin->getDefaultText(EGDT_MSG_BOX_NO));
// 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);
btnRect.LowerRightCorner.X += buttonWidth + buttonDistance;
btnRect.UpperLeftCorner.X += buttonWidth + buttonDistance;
// add buttons
if (!focusMe)
focusMe = NoButton;
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;
}
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);
......
......@@ -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;
......
......@@ -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";
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment