123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464 |
- // Copyright (C) 2002-2012 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_
|