From 604c7adeea9a05d94c3e6b73969c2d9ce376d792 Mon Sep 17 00:00:00 2001 From: auria Date: Wed, 24 Jun 2009 16:09:59 +0000 Subject: [PATCH] Widgets in modal dialogs can now be skinned git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/main/branches/irrlicht@3642 178a84e3-b1eb-0310-8ba1-8eac791a3b58 --- src/gui/modaldialog.cpp | 117 +++++++++++++++++++++++++++++++----- src/gui/modaldialog.hpp | 23 +++++++ src/gui/screen.cpp | 28 ++++++++- src/gui/widget.cpp | 26 ++++---- src/gui/widget.hpp | 33 ++++++---- src/input/input_manager.cpp | 2 +- 6 files changed, 185 insertions(+), 44 deletions(-) diff --git a/src/gui/modaldialog.cpp b/src/gui/modaldialog.cpp index 3dfcb0503..fb2d34a6e 100644 --- a/src/gui/modaldialog.cpp +++ b/src/gui/modaldialog.cpp @@ -15,16 +15,20 @@ // along with this program; if not, write to the Free Software // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +#include "config/player.hpp" #include "gui/engine.hpp" #include "gui/modaldialog.hpp" #include "gui/options_screen.hpp" #include "gui/state_manager.hpp" +#include "gui/widget.hpp" #include "network/network_manager.hpp" #include "race/race_manager.hpp" #include "utils/translation.hpp" using namespace irr; +namespace GUIEngine +{ // global instance of the current dialog if any static ModalDialog* modalWindow = NULL; @@ -50,6 +54,10 @@ bool ModalDialog::isADialogActive() { return modalWindow != NULL; } +ModalDialog* ModalDialog::getCurrent() +{ + return modalWindow; +} void ModalDialog::onEnterPressedInternal() { @@ -74,11 +82,37 @@ ModalDialog::ModalDialog(const float percentWidth, const float percentHeight) PressAKeyDialog::PressAKeyDialog(const float w, const float h) : ModalDialog(w, h) { - core::rect< s32 > area2(0, 0, m_area.getWidth(), m_area.getHeight()); - IGUIStaticText* label = GUIEngine::getGUIEnv()->addStaticText( stringw(_("Press a key")).c_str(), - area2, false /* border */, true /* word wrap */, - m_irrlicht_window); - label->setTextAlignment(EGUIA_CENTER, EGUIA_CENTER); + //core::rect< s32 > area2(0, 0, m_area.getWidth(), m_area.getHeight()); + //IGUIStaticText* label = GUIEngine::getGUIEnv()->addStaticText( stringw(_("Press a key")).c_str(), + // area2, false /* border */, true /* word wrap */, + // m_irrlicht_window); + //label->setTextAlignment(EGUIA_CENTER, EGUIA_CENTER); + + LabelWidget* widget = new LabelWidget(); + widget->m_type = WTYPE_LABEL; + widget->m_properties[PROP_TEXT] = _("Press a key"); + widget->m_properties[PROP_TEXT_ALIGN] = "center"; + widget->x = 0; + widget->y = 0; + widget->w = m_area.getWidth(); + widget->h = m_area.getHeight()/2; + widget->setParent(m_irrlicht_window); + + m_children.push_back(widget); + widget->add(); + + + ButtonWidget* widget2 = new ButtonWidget(); + widget2->m_type = WTYPE_BUTTON; // FIXME : shouldn't constructor set type? + widget2->m_properties[PROP_TEXT] = _("Press ESC to cancel"); // TODO : pressing this button should cancel + widget2->x = 15; + widget2->y = m_area.getHeight() - 60; + widget2->w = m_area.getWidth() - 30; + widget2->h = 50; + widget2->setParent(m_irrlicht_window); + + m_children.push_back(widget2); + widget2->add(); } // ------------------------------------------------------------------------------------------------------ @@ -87,12 +121,27 @@ PressAKeyDialog::PressAKeyDialog(const float w, const float h) : EnterPlayerNameDialog::EnterPlayerNameDialog(const float w, const float h) : ModalDialog(w, h) { - core::rect< s32 > area_top(0, 0, m_area.getWidth(), m_area.getHeight()/2); - IGUIStaticText* label = GUIEngine::getGUIEnv()->addStaticText( stringw(_("Enter the new player's name")).c_str(), - area_top, false /* border */, true /* word wrap */, - m_irrlicht_window); - label->setTextAlignment(EGUIA_CENTER, EGUIA_CENTER); + //core::rect< s32 > area_top(0, 0, m_area.getWidth(), m_area.getHeight()/2); + //IGUIStaticText* label = GUIEngine::getGUIEnv()->addStaticText( stringw(_("Enter the new player's name")).c_str(), + // area_top, false /* border */, true /* word wrap */, + // m_irrlicht_window); + // label->setTextAlignment(EGUIA_CENTER, EGUIA_CENTER); + LabelWidget* widget = new LabelWidget(); + widget->m_type = WTYPE_LABEL; + widget->m_properties[PROP_TEXT] = _("Enter the new player's name"); + widget->m_properties[PROP_TEXT_ALIGN] = "center"; + widget->x = 0; + widget->y = 0; + widget->w = m_area.getWidth(); + widget->h = m_area.getHeight()/2; + widget->setParent(m_irrlicht_window); + + m_children.push_back(widget); + widget->add(); + + // ---- + IGUIFont* font = GUIEngine::getFont(); const int textHeight = font->getDimension(L"X").Height; @@ -135,21 +184,37 @@ TrackInfoDialog::TrackInfoDialog(const char* trackName, ITexture* screenshot, co area_left, false /* border */, true /* word wrap */, m_irrlicht_window); + // TODO : preserve aspect ratio core::rect< s32 > area_right(m_area.getWidth()/2, y1, m_area.getWidth(), y2); IGUIImage* screenshotWidget = GUIEngine::getGUIEnv()->addImage( area_right, m_irrlicht_window ); screenshotWidget->setImage(screenshot); screenshotWidget->setScaleImage(true); - core::rect< s32 > area_bottom(0, y2, m_area.getWidth(), m_area.getHeight()); - IGUIStaticText* d = GUIEngine::getGUIEnv()->addStaticText( stringw(_("Number of laps")).c_str(), - area_bottom, false /* border */, true /* word wrap */, - m_irrlicht_window); + + SpinnerWidget* widget = new SpinnerWidget(); + widget->m_type = WTYPE_SPINNER; + widget->x = 0; + widget->y = y2; + widget->w = m_area.getWidth(); + widget->h = m_area.getHeight() - y2; + widget->setParent(m_irrlicht_window); + + widget->m_properties[PROP_MIN_VALUE] = "1"; + widget->m_properties[PROP_MAX_VALUE] = "99"; + + m_children.push_back(widget); + widget->add(); + widget->setValue(3); + + //IGUIStaticText* d = GUIEngine::getGUIEnv()->addStaticText( stringw(_("Number of laps")).c_str(), + // area_bottom, false /* border */, true /* word wrap */, + // m_irrlicht_window); a->setTextAlignment(EGUIA_CENTER, EGUIA_CENTER); b->setTextAlignment(EGUIA_CENTER, EGUIA_CENTER); - d->setTextAlignment(EGUIA_CENTER, EGUIA_CENTER); + //d->setTextAlignment(EGUIA_CENTER, EGUIA_CENTER); } // ------------------------------------------------------------------------------------------------------ @@ -179,3 +244,25 @@ void TrackInfoDialog::onEnterPressedInternal() race_manager->startNew(); } + + +PlayerInfoDialog::PlayerInfoDialog(Player* PlayerInfoDialog, const float w, const float h) : ModalDialog(w, h) +{ + ButtonWidget* widget = new ButtonWidget(); + widget->m_type = WTYPE_BUTTON; + widget->m_properties[PROP_TEXT] = _("Remove"); + widget->x = 0; + widget->y = 0; + widget->w = m_area.getWidth(); + widget->h = m_area.getHeight(); + widget->setParent(m_irrlicht_window); + + m_children.push_back(widget); + widget->add(); +} +void PlayerInfoDialog::onEnterPressedInternal() +{ +} + + +} diff --git a/src/gui/modaldialog.hpp b/src/gui/modaldialog.hpp index 53cd10004..533bbc94d 100644 --- a/src/gui/modaldialog.hpp +++ b/src/gui/modaldialog.hpp @@ -16,7 +16,14 @@ // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "irrlicht.h" +#include "utils/ptr_vector.hpp" +class Player; + +namespace GUIEngine +{ + class Widget; + /** * Base class, derive your own. * Only once instance at a time (if you create a 2nd the first will be destroyed). @@ -37,10 +44,13 @@ protected: virtual void onEnterPressedInternal(); public: + ptr_vector m_children; + virtual ~ModalDialog(); static void dismiss(); static void onEnterPressed(); + static ModalDialog* getCurrent(); static bool isADialogActive(); }; @@ -74,3 +84,16 @@ public: void onEnterPressedInternal(); }; +class PlayerInfoDialog : public ModalDialog +{ +public: + /** + * Creates a modal dialog with given percentage of screen width and height + */ + PlayerInfoDialog(Player* PlayerInfoDialog, + const float percentWidth, const float percentHeight); + void onEnterPressedInternal(); +}; + + +} diff --git a/src/gui/screen.cpp b/src/gui/screen.cpp index e45343043..60d92414e 100644 --- a/src/gui/screen.cpp +++ b/src/gui/screen.cpp @@ -310,12 +310,22 @@ void Screen::elementsWereDeleted(ptr_vector* within_vector) Widget* Screen::getWidget(const char* name) { - return getWidget(name, &m_widgets); + return getWidget(name, NULL); } // ----------------------------------------------------------------------------- Widget* Screen::getWidget(const char* name, ptr_vector* within_vector) { - if(within_vector == NULL) within_vector = &m_widgets; + if(within_vector == NULL) + { + within_vector = &m_widgets; + + // if a modal dialog is shown, search within it too + if(ModalDialog::isADialogActive()) + { + Widget* widgetWithinDialog = getWidget(name, &(ModalDialog::getCurrent()->m_children)); + if(widgetWithinDialog != NULL) return widgetWithinDialog; + } + } const unsigned short widgets_amount = within_vector->size(); @@ -337,7 +347,18 @@ Widget* Screen::getWidget(const char* name, ptr_vector* within_vector) // ----------------------------------------------------------------------------- Widget* Screen::getWidget(const int id, ptr_vector* within_vector) { - if(within_vector == NULL) within_vector = &m_widgets; + if(within_vector == NULL) + { + within_vector = &m_widgets; + + // if a modal dialog is shown, search within it too + if(ModalDialog::isADialogActive()) + { + Widget* widgetWithinDialog = getWidget(id, &(ModalDialog::getCurrent()->m_children)); + if(widgetWithinDialog != NULL) return widgetWithinDialog; + } + } + const unsigned short widgets_amount = within_vector->size(); for(int n=0; ngetFocus(); if(el == NULL) break; + Widget* w = getWidget( el->getID() ); if(w == NULL) break; diff --git a/src/gui/widget.cpp b/src/gui/widget.cpp index cea5db6e4..860b7167a 100644 --- a/src/gui/widget.cpp +++ b/src/gui/widget.cpp @@ -62,6 +62,7 @@ Widget::Widget() m_selected = false; m_event_handler = NULL; m_show_bounding_box = false; + m_parent = NULL; } // ----------------------------------------------------------------------------- /** @@ -231,6 +232,11 @@ void Widget::readCoords(Widget* parent) } +void Widget::setParent(IGUIElement* parent) +{ + m_parent = parent; +} + #if 0 #pragma mark - #pragma mark Button Widget @@ -240,7 +246,7 @@ void ButtonWidget::add() { rect widget_size = rect(x, y, x + w, y + h); stringw message = m_properties[PROP_TEXT].c_str(); - m_element = GUIEngine::getGUIEnv()->addButton(widget_size, NULL, ++id_counter, message.c_str(), L""); + m_element = GUIEngine::getGUIEnv()->addButton(widget_size, m_parent, ++id_counter, message.c_str(), L""); id = m_element->getID(); m_element->setTabOrder(id); @@ -267,7 +273,7 @@ void LabelWidget::add() else if(m_properties[PROP_TEXT_ALIGN] == "right") align = EGUIA_LOWERRIGHT; EGUI_ALIGNMENT valign = EGUIA_CENTER ; // TODO - make confiurable through XML file? - IGUIStaticText* irrwidget = GUIEngine::getGUIEnv()->addStaticText(message.c_str(), widget_size, false, word_wrap, NULL, -1); + IGUIStaticText* irrwidget = GUIEngine::getGUIEnv()->addStaticText(message.c_str(), widget_size, false, word_wrap, m_parent, -1); m_element = irrwidget; irrwidget->setTextAlignment( align, valign ); @@ -294,7 +300,7 @@ void CheckBoxWidget::add() stringw message = m_properties[PROP_TEXT].c_str(); //m_element = GUIEngine::getGUIEnv()->addCheckBox(true /* checked */, widget_size, NULL, ++id_counter, message.c_str()); - m_element = GUIEngine::getGUIEnv()->addButton(widget_size, NULL, ++id_counter, L""); + m_element = GUIEngine::getGUIEnv()->addButton(widget_size, m_parent, ++id_counter, L""); id = m_element->getID(); m_element->setTabOrder(id); m_element->setTabGroup(false); @@ -334,7 +340,7 @@ void IconButtonWidget::add() if(clickable) { widget_size = rect(x, y, x + w, y + h); - IGUIButton* btn = GUIEngine::getGUIEnv()->addButton(widget_size, NULL, ++id_counter, L""); + IGUIButton* btn = GUIEngine::getGUIEnv()->addButton(widget_size, m_parent, ++id_counter, L""); m_element = btn; btn->setUseAlphaChannel(true); btn->setImage(texture); @@ -349,7 +355,7 @@ void IconButtonWidget::add() widget_size = rect(x + x_gap/2, y, x + w - x_gap/2, y + h); - IGUIImage* btn = GUIEngine::getGUIEnv()->addImage(widget_size, NULL, ++id_counter_2); + IGUIImage* btn = GUIEngine::getGUIEnv()->addImage(widget_size, m_parent, ++id_counter_2); m_element = btn; btn->setUseAlphaChannel(true); btn->setImage(texture); @@ -361,7 +367,7 @@ void IconButtonWidget::add() if(message.size() > 0) { widget_size += position2d(0, widget_size.getHeight()); - label = GUIEngine::getGUIEnv()->addStaticText(message.c_str(), widget_size); + label = GUIEngine::getGUIEnv()->addStaticText(message.c_str(), widget_size, false, false /* word wrap */, m_parent); label->setTextAlignment(EGUIA_CENTER, EGUIA_UPPERLEFT); label->setTabStop(false); } @@ -393,12 +399,8 @@ void IconButtonWidget::add() void IconButtonWidget::setLabel(std::string new_label) { - std::cout << "trying to set label " << new_label.c_str() << std::endl; - if(label == NULL) return; - std::cout << "set label " << new_label.c_str() << std::endl; - label->setText( stringw(new_label.c_str()).c_str() ); } @@ -529,7 +531,7 @@ void RibbonWidget::add() rect widget_size = rect(x, y, x + w, y + h); - IGUIButton * btn = GUIEngine::getGUIEnv()->addButton(widget_size, NULL, ++id_counter, L""); + IGUIButton * btn = GUIEngine::getGUIEnv()->addButton(widget_size, m_parent, ++id_counter, L""); m_element = btn; const int subbuttons_amount = m_children.size(); @@ -733,7 +735,7 @@ void SpinnerWidget::add() } rect widget_size = rect(x, y, x + w, y + h); - IGUIButton * btn = GUIEngine::getGUIEnv()->addButton(widget_size, NULL, ++id_counter, L""); + IGUIButton * btn = GUIEngine::getGUIEnv()->addButton(widget_size, m_parent, ++id_counter, L""); m_element = btn; // left arrow diff --git a/src/gui/widget.hpp b/src/gui/widget.hpp index b135085ae..97c1a8cd1 100644 --- a/src/gui/widget.hpp +++ b/src/gui/widget.hpp @@ -86,12 +86,6 @@ namespace GUIEngine */ bool m_selected; - /** - * Create and add the irrLicht widget(s) associated with this object. - * Call after Widget was read from XML file and laid out. - */ - virtual void add() {} - /** * called when left/right keys pressed and focus is on widget. * Returns 'true' if main event handler should be notified of a change. @@ -124,6 +118,8 @@ namespace GUIEngine */ Widget* m_event_handler; + IGUIElement* m_parent; + static bool convertToCoord(std::string& x, int* absolute, int* percentage); public: Widget(); @@ -131,6 +127,14 @@ namespace GUIEngine bool m_show_bounding_box; + /** + * Create and add the irrLicht widget(s) associated with this object. + * Call after Widget was read from XML file and laid out. + */ + virtual void add() {} + + void setParent(IGUIElement* parent); + /** * If this widget has any children, they go here. Children can be either * specified in the XML file (e.g. Ribbon or Div children), or can also @@ -168,27 +172,29 @@ namespace GUIEngine class ButtonWidget : public Widget { - void add(); public: + void add(); virtual ~ButtonWidget() {} void setLabel(const char* label); }; class LabelWidget : public Widget { - void add(); public: + void add(); virtual ~LabelWidget() {} }; class CheckBoxWidget : public Widget { - void add(); bool m_state; bool transmitEvent(Widget* w, std::string& originator); + public: CheckBoxWidget(); virtual ~CheckBoxWidget() {} + + void add(); bool getState() const { return m_state; } void setState(const bool enabled) { m_state = enabled; } }; @@ -204,14 +210,14 @@ namespace GUIEngine bool transmitEvent(Widget* w, std::string& originator); bool rightPressed(); bool leftPressed(); - void add(); public: SpinnerWidget(const bool gauge=false); virtual ~SpinnerWidget() {} + void setValue(const int new_value); void addLabel(std::string label); - + void add(); bool isGauge() const { return m_gauge; } int getValue() const { return m_value; } int getMax() const { return m_max; } @@ -221,11 +227,12 @@ namespace GUIEngine class IconButtonWidget : public Widget { bool clickable; - void add(); IGUIStaticText* label; public: - virtual ~IconButtonWidget() {} IconButtonWidget(const bool clickable=true); + virtual ~IconButtonWidget() {} + + void add(); void setLabel(std::string new_label); }; diff --git a/src/input/input_manager.cpp b/src/input/input_manager.cpp index 4a5a75389..26b9614b8 100644 --- a/src/input/input_manager.cpp +++ b/src/input/input_manager.cpp @@ -198,7 +198,7 @@ void InputManager::input(Input::InputType type, int deviceID, int btnID, int axi else if(btnID == KEY_RIGHT) action = PA_RIGHT; else if(btnID == KEY_SPACE) action = PA_FIRE; - if(btnID == KEY_RETURN && ModalDialog::isADialogActive()) ModalDialog::onEnterPressed(); + if(btnID == KEY_RETURN && GUIEngine::ModalDialog::isADialogActive()) GUIEngine::ModalDialog::onEnterPressed(); if(action != PA_FIRST) {