From 9e4d29dd2bfdd63f3d0594a81dcada6fee5ec45f Mon Sep 17 00:00:00 2001 From: bitplane Date: Wed, 29 Aug 2007 23:37:24 +0000 Subject: [PATCH] CuteAlien's menu changes and fixes, CuteAlien/StarSonata's coloured listbox item extension. Added a close event for windows (and in future other elements), absorbing this event will prevent the window from closing. Used the new skin icon in the gui editor's resize button. git-svn-id: svn://svn.code.sf.net/p/irrlicht/code/trunk@879 dfc29bdd-3216-0410-991c-e03cc46cb475 --- changes.txt | 4 + include/EDebugSceneTypes.h | 2 +- include/ESceneNodeAnimatorTypes.h | 2 +- include/IEventReceiver.h | 13 +- include/IGUIListBox.h | 55 +++++- source/Irrlicht/CGUIContextMenu.cpp | 46 ++++- source/Irrlicht/CGUIContextMenu.h | 7 +- source/Irrlicht/CGUIListBox.cpp | 292 +++++++++++++++++++++++----- source/Irrlicht/CGUIListBox.h | 61 +++++- source/Irrlicht/CGUIMenu.cpp | 55 +++--- source/Irrlicht/CGUIMenu.h | 4 +- source/Irrlicht/CGUIModalScreen.cpp | 11 +- source/Irrlicht/CGUIWindow.cpp | 24 ++- source/Irrlicht/Irrlicht8.0.vcproj | 10 +- tools/GUIEditor/CGUIEditWindow.cpp | 7 +- tools/GUIEditor/CGUIEditWindow.h | 19 +- tools/GUIEditor/main.cpp | 2 + 17 files changed, 493 insertions(+), 121 deletions(-) diff --git a/changes.txt b/changes.txt index e98b090e..137f86be 100644 --- a/changes.txt +++ b/changes.txt @@ -95,6 +95,10 @@ Changes in version 1.4 (... 2007) GUI: + - Fixes to menu and listbox (de)serialization, and custom listbox colors by CuteAlien. + + - Added EGET_ELEMENT_CLOSED GUI event type. Absorb this event to cancel closing a window. + - Added _IRR_COMPILE_WITH_GUI_ to allow compiling without the GUI. This is useful if you use another GUI system (ie CEGUI) or are using Irrlicht inside another window. You will have to supply an external IGUIFont if you wish diff --git a/include/EDebugSceneTypes.h b/include/EDebugSceneTypes.h index f7754d87..d90998bd 100644 --- a/include/EDebugSceneTypes.h +++ b/include/EDebugSceneTypes.h @@ -29,7 +29,7 @@ namespace scene EDS_MESH_WIRE_OVERLAY = 8, //! Temporary use transparency Material Type - EDS_HALF_TRANSPARENCY= 16, + EDS_HALF_TRANSPARENCY = 16, //! Show Bounding Boxes of all MeshBuffers EDS_BBOX_BUFFERS = 32, diff --git a/include/ESceneNodeAnimatorTypes.h b/include/ESceneNodeAnimatorTypes.h index d5b44b78..6eebc993 100644 --- a/include/ESceneNodeAnimatorTypes.h +++ b/include/ESceneNodeAnimatorTypes.h @@ -33,7 +33,7 @@ namespace scene //! Collision respose scene node animator ESNAT_COLLISION_RESPONSE, - //! Amount of build in scene node animators + //! Amount of built-in scene node animators ESNAT_COUNT, //! Unknown scene node animator diff --git a/include/IEventReceiver.h b/include/IEventReceiver.h index 071af62c..37e3f886 100644 --- a/include/IEventReceiver.h +++ b/include/IEventReceiver.h @@ -85,18 +85,25 @@ namespace irr enum EGUI_EVENT_TYPE { //! A gui element has lost its focus. - //! GUIEvent.Caller is losing the focus to GUIEvent.Element + //! GUIEvent.Caller is losing the focus to GUIEvent.Element. + //! If the event is absorbed then the focus will not be changed. EGET_ELEMENT_FOCUS_LOST = 0, //! A gui element has got the focus. + //! If the event is absorbed then the focus will not be changed. EGET_ELEMENT_FOCUSED, - //! A gui element was hovered. + //! The mouse cursor hovered over a gui element. EGET_ELEMENT_HOVERED, - //! A hovered gui element was left + //! The mouse cursor left the hovered element. EGET_ELEMENT_LEFT, + //! An element would like to close. + //! Windows and context menus use this event when they would like to close, + //! this can be cancelled by absorbing the event. + EGET_ELEMENT_CLOSED, + //! A button was clicked. EGET_BUTTON_CLICKED, diff --git a/include/IGUIListBox.h b/include/IGUIListBox.h index 490aa40d..1d60d0af 100644 --- a/include/IGUIListBox.h +++ b/include/IGUIListBox.h @@ -2,10 +2,11 @@ // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h -#ifndef __I_GUI_LIST_BOX_BAR_H_INCLUDED__ -#define __I_GUI_LIST_BOX_BAR_H_INCLUDED__ +#ifndef __I_GUI_LIST_BOX_H_INCLUDED__ +#define __I_GUI_LIST_BOX_H_INCLUDED__ #include "IGUIElement.h" +#include "SColor.h" namespace irr { @@ -14,11 +15,26 @@ namespace gui class IGUIFont; class IGUISpriteBank; + //! Enumeration for listbox colors + enum EGUI_LISTBOX_COLOR + { + //! Color of text + EGUI_LBC_TEXT=0, + //! Color of selected text + EGUI_LBC_TEXT_HIGHLIGHT, + //! Color of icon + EGUI_LBC_ICON, + //! Color of selected icon + EGUI_LBC_ICON_HIGHLIGHT, + //! Not used, just counts the number of available colors + EGUI_LBC_COUNT + }; + + //! Default list box GUI element. class IGUIListBox : public IGUIElement { public: - //! constructor IGUIListBox(IGUIEnvironment* environment, IGUIElement* parent, s32 id, core::rect rectangle) : IGUIElement(EGUIET_LIST_BOX, environment, parent, id, rectangle) {} @@ -70,11 +86,40 @@ namespace gui //! returns true if automatic scrolling is enabled, false if not. virtual bool isAutoScrollEnabled() = 0; - }; + //! set all item colors at given index to color + virtual void setItemOverrideColor(s32 index, const video::SColor &color) = 0; + + //! set all item colors of specified type at given index to color + virtual void setItemOverrideColor(s32 index, EGUI_LISTBOX_COLOR colorType, const video::SColor &color) = 0; + + //! clear all item colors at index + virtual void clearItemOverrideColor(s32 index) = 0; + + //! clear item color at index for given colortype + virtual void clearItemOverrideColor(s32 index, EGUI_LISTBOX_COLOR colorType) = 0; + + //! has the item at index it's color overwritten? + virtual bool hasItemOverrideColor(s32 index, EGUI_LISTBOX_COLOR colorType) = 0; + + //! return the overwrite color at given item index. + virtual video::SColor getItemOverrideColor(s32 index, EGUI_LISTBOX_COLOR colorType) = 0; + + //! return the default color which is used for the given colorType + virtual video::SColor getItemDefaultColor(EGUI_LISTBOX_COLOR colorType) = 0; + + //! set the item at the given index + virtual void setItem(s32 index, const wchar_t* text, s32 icon) = 0; + + //! Insert the item at the given index + //! Return the index on success or -1 on failure. + virtual s32 insertItem(s32 index, const wchar_t* text, s32 icon) = 0; + + //! Swap the items at the given indices + virtual void swapItems(s32 index1, s32 index2) = 0; +}; } // end namespace gui } // end namespace irr #endif - diff --git a/source/Irrlicht/CGUIContextMenu.cpp b/source/Irrlicht/CGUIContextMenu.cpp index 6abc053f..5ebbd8c7 100644 --- a/source/Irrlicht/CGUIContextMenu.cpp +++ b/source/Irrlicht/CGUIContextMenu.cpp @@ -94,7 +94,14 @@ void CGUIContextMenu::setSubMenu(s32 index, CGUIContextMenu* menu) menu->setVisible(false); if (Items[index].SubMenu) + { menu->grab(); + menu->AllowFocus = false; + if ( Environment->getFocus() == menu ) + { + Environment->setFocus( this ); + } + } recalculateSize(); } @@ -215,7 +222,7 @@ bool CGUIContextMenu::OnEvent(SEvent event) switch(event.GUIEvent.EventType) { case EGET_ELEMENT_FOCUS_LOST: - if (event.GUIEvent.Caller == this && !isMyChild(event.GUIEvent.Element)) + if (event.GUIEvent.Caller == this && !isMyChild(event.GUIEvent.Element) && AllowFocus) { // set event parent of submenus setEventParent(Parent); @@ -247,7 +254,7 @@ bool CGUIContextMenu::OnEvent(SEvent event) return true; case EMIE_MOUSE_MOVED: if (Environment->hasFocus(this)) - highlight(core::position2d(event.MouseInput.X, event.MouseInput.Y)); + highlight(core::position2d(event.MouseInput.X, event.MouseInput.Y), true); return true; } break; @@ -324,7 +331,7 @@ s32 CGUIContextMenu::sendClick(core::position2d p) //! returns true, if an element was highligted -bool CGUIContextMenu::highlight(core::position2d p) +bool CGUIContextMenu::highlight(core::position2d p, bool canOpenSubMenu) { // get number of open submenu s32 openmenu = -1; @@ -339,7 +346,7 @@ bool CGUIContextMenu::highlight(core::position2d p) // delegate highlight operation to submenu if (openmenu != -1) { - if (Items[openmenu].SubMenu->highlight(p)) + if (Items[openmenu].SubMenu->highlight(p, canOpenSubMenu)) { HighLighted = openmenu; ChangeTime = os::Timer::getTime(); @@ -355,9 +362,14 @@ bool CGUIContextMenu::highlight(core::position2d p) ChangeTime = os::Timer::getTime(); // make submenus visible/invisible - for (s32 j=0; j<(s32)Items.size(); ++j) - if (Items[j].SubMenu) - Items[j].SubMenu->setVisible(j == i); + for (s32 j=0; j<(s32)Items.size(); ++j) + if (Items[j].SubMenu) + { + if ( j == i && canOpenSubMenu ) + Items[j].SubMenu->setVisible(true); + else if ( j != i ) + Items[j].SubMenu->setVisible(false); + } return true; } @@ -479,7 +491,6 @@ void CGUIContextMenu::draw() core::rect r = rect; r.LowerRightCorner.X = r.UpperLeftCorner.X - 15; r.UpperLeftCorner.X = r.LowerRightCorner.X + 15; - sprites->draw2DSprite(skin->getIcon(EGDI_CHECK_BOX_CHECKED), r.getCenter(), clip, skin->getColor(c), (i == HighLighted) ? ChangeTime : 0, @@ -691,9 +702,28 @@ void CGUIContextMenu::setEventParent(IGUIElement *parent) } } +bool CGUIContextMenu::hasOpenSubMenu() +{ + for (s32 i=0; i<(s32)Items.size(); ++i) + if (Items[i].SubMenu) + if ( Items[i].SubMenu->isVisible() ) + return true; + return false; +} + +void CGUIContextMenu::closeAllSubMenus() +{ + for (s32 i=0; i<(s32)Items.size(); ++i) + if (Items[i].SubMenu) + Items[i].SubMenu->setVisible(false); + + //HighLighted = -1; +} + } // end namespace } // end namespace + #endif // _IRR_COMPILE_WITH_GUI_ diff --git a/source/Irrlicht/CGUIContextMenu.h b/source/Irrlicht/CGUIContextMenu.h index 0ad13e2c..f6ac3062 100644 --- a/source/Irrlicht/CGUIContextMenu.h +++ b/source/Irrlicht/CGUIContextMenu.h @@ -98,6 +98,9 @@ namespace gui protected: + void closeAllSubMenus(); + bool hasOpenSubMenu(); + struct SItem { core::stringw Text; @@ -112,8 +115,8 @@ namespace gui virtual void recalculateSize(); - //! returns true, if an element was highligted - virtual bool highlight(core::position2d p); + //! returns true, if an element was highlighted + virtual bool highlight(core::position2d p, bool canOpenSubMenu); //! sends a click Returns: //! 0 if click went outside of the element, diff --git a/source/Irrlicht/CGUIListBox.cpp b/source/Irrlicht/CGUIListBox.cpp index a0795f60..c1418d7d 100644 --- a/source/Irrlicht/CGUIListBox.cpp +++ b/source/Irrlicht/CGUIListBox.cpp @@ -5,6 +5,7 @@ #include "CGUIListBox.h" #ifdef _IRR_COMPILE_WITH_GUI_ +#include "CGUIListBox.h" #include "IGUISkin.h" #include "IGUIEnvironment.h" #include "IVideoDriver.h" @@ -102,14 +103,7 @@ s32 CGUIListBox::getIcon(s32 id) const //! adds an list item, returns id of item s32 CGUIListBox::addItem(const wchar_t* text) { - ListItem i; - i.text = text; - - Items.push_back(i); - recalculateItemHeight(); - recalculateScrollPos(); - - return Items.size() - 1; + return addItem(text, -1); } //! adds an list item, returns id of item @@ -522,14 +516,36 @@ void CGUIListBox::draw() core::position2di iconPos = textRect.UpperLeftCorner; iconPos.Y += textRect.getHeight() / 2; iconPos.X += ItemsIconWidth/2; - IconBank->draw2DSprite( (u32)Items[i].icon, iconPos, &clientClip, - skin->getColor((i==Selected && hl) ? EGDC_ICON_HIGH_LIGHT : EGDC_ICON), - (i==Selected && hl) ? selectTime : 0 , (i==Selected) ? os::Timer::getTime() : 0, false, true); + + if ( i==Selected && hl ) + { + IconBank->draw2DSprite( (u32)Items[i].icon, iconPos, &clientClip, + hasItemOverrideColor(i, EGUI_LBC_ICON_HIGHLIGHT) ? getItemOverrideColor(i, EGUI_LBC_ICON_HIGHLIGHT) : getItemDefaultColor(EGUI_LBC_ICON_HIGHLIGHT), + selectTime, os::Timer::getTime(), false, true); + } + else + { + IconBank->draw2DSprite( (u32)Items[i].icon, iconPos, &clientClip, + hasItemOverrideColor(i, EGUI_LBC_ICON) ? getItemOverrideColor(i, EGUI_LBC_ICON) : getItemDefaultColor(EGUI_LBC_ICON), + 0 , (i==Selected) ? os::Timer::getTime() : 0, false, true); + } + } textRect.UpperLeftCorner.X += ItemsIconWidth+3; - Font->draw(Items[i].text.c_str(), textRect, skin->getColor((i==Selected && hl) ? EGDC_HIGH_LIGHT_TEXT : EGDC_BUTTON_TEXT), false, true, &clientClip); + if ( i==Selected && hl ) + { + Font->draw(Items[i].text.c_str(), textRect, + hasItemOverrideColor(i, EGUI_LBC_TEXT_HIGHLIGHT) ? getItemOverrideColor(i, EGUI_LBC_TEXT_HIGHLIGHT) : getItemDefaultColor(EGUI_LBC_TEXT_HIGHLIGHT), + false, true, &clientClip); + } + else + { + Font->draw(Items[i].text.c_str(), textRect, + hasItemOverrideColor(i, EGUI_LBC_TEXT) ? getItemOverrideColor(i, EGUI_LBC_TEXT) : getItemDefaultColor(EGUI_LBC_TEXT), + false, true, &clientClip); + } textRect.UpperLeftCorner.X -= ItemsIconWidth+3; } @@ -553,19 +569,7 @@ s32 CGUIListBox::addItem(const wchar_t* text, s32 icon) Items.push_back(i); recalculateItemHeight(); - - if (IconBank && icon > -1 && - IconBank->getSprites().size() > (u32)icon && - IconBank->getSprites()[(u32)icon].Frames.size()) - { - u32 rno = IconBank->getSprites()[(u32)icon].Frames[0].rectNumber; - if (IconBank->getPositions().size() > rno) - { - const s32 w = IconBank->getPositions()[rno].getWidth(); - if (w > ItemsIconWidth) - ItemsIconWidth = w; - } - } + recalculateItemWidth(icon); return Items.size() - 1; } @@ -609,6 +613,32 @@ bool CGUIListBox::isAutoScrollEnabled() return AutoScroll; } +bool CGUIListBox::getSerializationLabels(EGUI_LISTBOX_COLOR colorType, core::stringc & useColorLabel, core::stringc & colorLabel) +{ + switch ( colorType ) + { + case EGUI_LBC_TEXT: + useColorLabel = "UseColText"; + colorLabel = "ColText"; + break; + case EGUI_LBC_TEXT_HIGHLIGHT: + useColorLabel = "UseColTextHl"; + colorLabel = "ColTextHl"; + break; + case EGUI_LBC_ICON: + useColorLabel = "UseColIcon"; + colorLabel = "ColIcon"; + break; + case EGUI_LBC_ICON_HIGHLIGHT: + useColorLabel = "UseColIconHl"; + colorLabel = "ColIconHl"; + break; + default: + return false; + } + return true; +} + //! Writes attributes of the element. void CGUIListBox::serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options=0) { @@ -619,49 +649,215 @@ void CGUIListBox::serializeAttributes(io::IAttributes* out, io::SAttributeReadWr out->addBool ("MoveOverSelect", MoveOverSelect); out->addBool ("AutoScroll", AutoScroll); - // todo: save list of items and icons. - /*core::array tmpText; - core::array tmpIcons; + // MICHA, StarSonata + // I also don't know yet how to handle icons, but added some text+color serialization now + // I did it the same way it's done for the context menus + out->addInt("ItemCount", Items.size()); u32 i; for (i=0;iaddString(label.c_str(), Items[i].text.c_str() ); + + for ( s32 c=0; c < (s32)EGUI_LBC_COUNT; ++c ) + { + core::stringc useColorLabel, colorLabel; + if ( !getSerializationLabels((EGUI_LISTBOX_COLOR)c, useColorLabel, colorLabel) ) + return; + label = useColorLabel; label += i; + if ( Items[i].OverrideColors[c].Use ) + { + out->addBool(label.c_str(), true ); + label = colorLabel; label += i; + out->addColor(label.c_str(), Items[i].OverrideColors[c].Color); + } + else + { + out->addBool(label.c_str(), false ); + } + } } - - out->addArray ("ItemText", tmpText); - out->addArray ("ItemIcons", tmpIcons); - - out->addInt ("Selected", Selected); - */ - } //! Reads attributes of the element void CGUIListBox::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options=0) { + clear(); + DrawBack = in->getAttributeAsBool("DrawBack"); MoveOverSelect = in->getAttributeAsBool("MoveOverSelect"); AutoScroll = in->getAttributeAsBool("AutoScroll"); IGUIListBox::deserializeAttributes(in,options); - // read arrays - /* - core::array tmpText; - core::array tmpIcons; + // MICHA, StarSonata + // I also don't know yet how to handle icons, but added some text+color serialization now + // I did it the same way it's done for the context menus + s32 count = in->getAttributeAsInt("ItemCount"); + for (s32 i=0; i<(s32)count; ++i) + { + core::stringc label; + ListItem item; - tmpText = in->getAttributeAsArray("ItemText"); - tmpIcons = in->getAttributeAsArray("ItemIcons"); - u32 i; - for (i=0; igetAttributeAsStringW(label.c_str()); - this->setSelected(in->getAttributeAsInt("Selected")); - */ + addItem(item.text.c_str(), item.icon); + for ( s32 c=0; c < (s32)EGUI_LBC_COUNT; ++c ) + { + core::stringc useColorLabel, colorLabel; + if ( !getSerializationLabels((EGUI_LISTBOX_COLOR)c, useColorLabel, colorLabel) ) + return; + label = useColorLabel; label += i; + Items[i].OverrideColors[c].Use = in->getAttributeAsBool(label.c_str()); + if ( Items[i].OverrideColors[c].Use ) + { + label = colorLabel; label += i; + Items[i].OverrideColors[c].Color = in->getAttributeAsColor(label.c_str()); + } + } + } } +// MICHA, StarSonata +void CGUIListBox::recalculateItemWidth(s32 icon) +{ + if (IconBank && icon > -1 && + IconBank->getSprites().size() > (u32)icon && + IconBank->getSprites()[(u32)icon].Frames.size()) + { + u32 rno = IconBank->getSprites()[(u32)icon].Frames[0].rectNumber; + if (IconBank->getPositions().size() > rno) + { + const s32 w = IconBank->getPositions()[rno].getWidth(); + if (w > ItemsIconWidth) + ItemsIconWidth = w; + } + } +} + +// MICHA, StarSonata +void CGUIListBox::setItem(s32 index, const wchar_t* text, s32 icon) +{ + if ( index < 0 || index >= (s32)Items.size() ) + return; + + Items[index].text = text; + Items[index].icon = icon; + + recalculateItemHeight(); + recalculateItemWidth(icon); +} + +// MICHA, StarSonata +//! Insert the item at the given index +//! Return the index on success or -1 on failure. +s32 CGUIListBox::insertItem(s32 index, const wchar_t* text, s32 icon) +{ + if ( index < 0 ) + return -1; + ListItem i; + i.text = text; + i.icon = icon; + + Items.insert(i, index); + recalculateItemHeight(); + recalculateItemWidth(icon); + + return index; +} + +// MICHA, StarSonata +void CGUIListBox::swapItems(s32 index1, s32 index2) +{ + if ( index1 < 0 || index2 < 0 || index1 >= (s32)Items.size() || index2 >= (s32)Items.size() ) + return; + + ListItem dummmy = Items[index1]; + Items[index1] = Items[index2]; + Items[index2] = dummmy; +} + +// MICHA, StarSonata +void CGUIListBox::setItemOverrideColor(s32 index, const video::SColor &color) +{ + for ( s32 c=0; c < (s32)EGUI_LBC_COUNT; ++c ) + { + Items[index].OverrideColors[c].Use = true; + Items[index].OverrideColors[c].Color = color; + } +} + +// MICHA, StarSonata +void CGUIListBox::setItemOverrideColor(s32 index, EGUI_LISTBOX_COLOR colorType, const video::SColor &color) +{ + if ( index < 0 || index >= (s32)Items.size() || colorType < 0 || colorType >= EGUI_LBC_COUNT ) + return; + + Items[index].OverrideColors[colorType].Use = true; + Items[index].OverrideColors[colorType].Color = color; +} + +// MICHA, StarSonata +void CGUIListBox::clearItemOverrideColor(s32 index) +{ + for (s32 c=0; c < (s32)EGUI_LBC_COUNT; ++c ) + { + Items[index].OverrideColors[c].Use = false; + } +} + +// MICHA, StarSonata +void CGUIListBox::clearItemOverrideColor(s32 index, EGUI_LISTBOX_COLOR colorType) +{ + if ( index < 0 || index >= (s32)Items.size() || colorType < 0 || colorType >= EGUI_LBC_COUNT ) + return; + + Items[index].OverrideColors[colorType].Use = false; +} + +// MICHA, StarSonata +bool CGUIListBox::hasItemOverrideColor(s32 index, EGUI_LISTBOX_COLOR colorType) +{ + if ( index < 0 || index >= (s32)Items.size() || colorType < 0 || colorType >= EGUI_LBC_COUNT ) + return false; + + return Items[index].OverrideColors[colorType].Use; +} + +// MICHA, StarSonata +video::SColor CGUIListBox::getItemOverrideColor(s32 index, EGUI_LISTBOX_COLOR colorType) +{ + if ( index < 0 || index >= (s32)Items.size() || colorType < 0 || colorType >= EGUI_LBC_COUNT ) + return video::SColor(); + + return Items[index].OverrideColors[colorType].Color; +} + +// MICHA, StarSonata +video::SColor CGUIListBox::getItemDefaultColor(EGUI_LISTBOX_COLOR colorType) +{ + IGUISkin* skin = Environment->getSkin(); + if ( !skin ) + return video::SColor(); + + switch ( colorType ) + { + case EGUI_LBC_TEXT: + return skin->getColor(EGDC_BUTTON_TEXT); + case EGUI_LBC_TEXT_HIGHLIGHT: + return skin->getColor(EGDC_HIGH_LIGHT_TEXT); + case EGUI_LBC_ICON: + return skin->getColor(EGDC_ICON); + case EGUI_LBC_ICON_HIGHLIGHT: + return skin->getColor(EGDC_ICON_HIGH_LIGHT); + default: + return video::SColor(); + } +} } // end namespace gui diff --git a/source/Irrlicht/CGUIListBox.h b/source/Irrlicht/CGUIListBox.h index 7fced7cb..8bba1c2b 100644 --- a/source/Irrlicht/CGUIListBox.h +++ b/source/Irrlicht/CGUIListBox.h @@ -2,8 +2,8 @@ // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h -#ifndef __C_GUI_LIST_BOX_BAR_H_INCLUDED__ -#define __C_GUI_LIST_BOX_BAR_H_INCLUDED__ +#ifndef __C_GUI_LIST_BOX_H_INCLUDED__ +#define __C_GUI_LIST_BOX_H_INCLUDED__ #include "IrrCompileConfig.h" #ifdef _IRR_COMPILE_WITH_GUI_ @@ -22,7 +22,6 @@ namespace gui class CGUIListBox : public IGUIListBox { public: - //! constructor CGUIListBox(IGUIEnvironment* environment, IGUIElement* parent, s32 id, core::rect rectangle, bool clip=true, @@ -89,20 +88,74 @@ namespace gui //! Reads attributes of the element virtual void deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options); + // MICHA, StarSonata, multicolor support + //! set all item colors at given index to color + virtual void setItemOverrideColor(s32 index, const video::SColor &color); + + //! set all item colors of specified type at given index to color + virtual void setItemOverrideColor(s32 index, EGUI_LISTBOX_COLOR colorType, const video::SColor &color); + + //! clear all item colors at index + virtual void clearItemOverrideColor(s32 index); + + //! clear item color at index for given colortype + virtual void clearItemOverrideColor(s32 index, EGUI_LISTBOX_COLOR colorType); + + //! has the item at index it's color overwritten? + virtual bool hasItemOverrideColor(s32 index, EGUI_LISTBOX_COLOR colorType); + + //! return the overwrite color at given item index. + virtual video::SColor getItemOverrideColor(s32 index, EGUI_LISTBOX_COLOR colorType); + + //! return the default color which is used for the given colorType + virtual video::SColor getItemDefaultColor(EGUI_LISTBOX_COLOR colorType); + + // MICHA, StarSonata + //! set the item at the given index + virtual void setItem(s32 index, const wchar_t* text, s32 icon); + + // MICHA, StarSonata + //! Insert the item at the given index + //! Return the index on success or -1 on failure. + virtual s32 insertItem(s32 index, const wchar_t* text, s32 icon); + + // MICHA, StarSonata + //! Swap the items at the given indices + virtual void swapItems(s32 index1, s32 index2); + private: struct ListItem { - ListItem() : icon(-1) {} + ListItem() : icon(-1) + {} core::stringw text; s32 icon; + + // MICHA, StarSonata + // A multicolor extension + struct ListItemOverrideColor + { + ListItemOverrideColor() : Use(false) {} + bool Use; + video::SColor Color; + }; + ListItemOverrideColor OverrideColors[EGUI_LBC_COUNT]; }; void recalculateItemHeight(); void selectNew(s32 ypos, bool onlyHover=false); void recalculateScrollPos(); + // MICHA, StarSonata + // extracted that function to avoid copy&paste code + void recalculateItemWidth(s32 icon); + + // MICHA, StarSonata + // get labels used for serialization + bool getSerializationLabels(EGUI_LISTBOX_COLOR colorType, core::stringc & useColorLabel, core::stringc & colorLabel); + core::array< ListItem > Items; s32 Selected; s32 ItemHeight; diff --git a/source/Irrlicht/CGUIMenu.cpp b/source/Irrlicht/CGUIMenu.cpp index 222bfde4..23129462 100644 --- a/source/Irrlicht/CGUIMenu.cpp +++ b/source/Irrlicht/CGUIMenu.cpp @@ -102,46 +102,49 @@ bool CGUIMenu::OnEvent(SEvent event) { case gui::EGET_ELEMENT_FOCUS_LOST: if (event.GUIEvent.Caller == this && !isMyChild(event.GUIEvent.Element)) + { closeAllSubMenus(); + HighLighted = -1; + } break; case gui::EGET_ELEMENT_FOCUSED: if (event.GUIEvent.Caller == this && Parent) + { Parent->bringToFront(this); - + } + break; } break; case EET_MOUSE_INPUT_EVENT: switch(event.MouseInput.Event) { - case EMIE_LMOUSE_LEFT_UP: - { - core::position2d p(event.MouseInput.X, event.MouseInput.Y); - if (AbsoluteClippingRect.isPointInside(p)) - { - if (HighLighted != -1) - Environment->removeFocus(this); - else - highlight(core::position2d(event.MouseInput.X, event.MouseInput.Y)); - } - else - { - s32 t = sendClick(p); - if ((t==0 || t==1) && Environment->hasFocus(this)) - Environment->removeFocus(this); - } - } - return true; case EMIE_LMOUSE_PRESSED_DOWN: + { if (!Environment->hasFocus(this)) { Environment->setFocus(this); if (Parent) Parent->bringToFront(this); } + + core::position2d p(event.MouseInput.X, event.MouseInput.Y); + bool shouldCloseSubMenu = hasOpenSubMenu(); + if (!AbsoluteClippingRect.isPointInside(p)) + { + shouldCloseSubMenu = false; + s32 t = sendClick(p); + if ((t==0 || t==1) && Environment->hasFocus(this)) + Environment->removeFocus(this); + } + highlight(core::position2d(event.MouseInput.X, event.MouseInput.Y), true); + if ( shouldCloseSubMenu ) + closeAllSubMenus(); + return true; + } case EMIE_MOUSE_MOVED: if (Environment->hasFocus(this)) - highlight(core::position2d(event.MouseInput.X, event.MouseInput.Y)); + highlight(core::position2d(event.MouseInput.X, event.MouseInput.Y), hasOpenSubMenu()); return true; } break; @@ -229,17 +232,6 @@ core::rect CGUIMenu::getRect(const SItem& i, const core::rect& absolut return getHRect(i, absolute); } - -void CGUIMenu::closeAllSubMenus() -{ - for (s32 i=0; i<(s32)Items.size(); ++i) - if (Items[i].SubMenu) - Items[i].SubMenu->setVisible(false); - - HighLighted = -1; -} - - void CGUIMenu::updateAbsolutePosition() { if (Parent) @@ -252,4 +244,5 @@ void CGUIMenu::updateAbsolutePosition() } // end namespace } // end namespace + #endif // _IRR_COMPILE_WITH_GUI_ diff --git a/source/Irrlicht/CGUIMenu.h b/source/Irrlicht/CGUIMenu.h index bf25931e..4b44accb 100644 --- a/source/Irrlicht/CGUIMenu.h +++ b/source/Irrlicht/CGUIMenu.h @@ -44,13 +44,11 @@ namespace gui //! Gets drawing rect of Item virtual core::rect getRect(const SItem& i, const core::rect& absolute); - - void closeAllSubMenus(); - }; } // end namespace gui } // end namespace irr + #endif // __C_GUI_MENU_H_INCLUDED__ #endif // _IRR_COMPILE_WITH_GUI_ diff --git a/source/Irrlicht/CGUIModalScreen.cpp b/source/Irrlicht/CGUIModalScreen.cpp index 4e943239..8723f626 100644 --- a/source/Irrlicht/CGUIModalScreen.cpp +++ b/source/Irrlicht/CGUIModalScreen.cpp @@ -45,19 +45,26 @@ bool CGUIModalScreen::OnEvent(SEvent event) switch(event.GUIEvent.EventType) { case EGET_ELEMENT_FOCUSED: + // only children are allowed the focus if (event.GUIEvent.Caller != this && !isMyChild(event.GUIEvent.Caller)) Environment->setFocus(this); return false; case EGET_ELEMENT_FOCUS_LOST: + // only children are allowed the focus if (!(isMyChild(event.GUIEvent.Element) || event.GUIEvent.Element == this)) { MouseDownTime = os::Timer::getTime(); return true; } else + { return IGUIElement::OnEvent(event); - + } break; + case EGET_ELEMENT_CLOSED: + // do not interfere with children being removed + return IGUIElement::OnEvent(event); + } case EET_MOUSE_INPUT_EVENT: switch(event.MouseInput.Event) @@ -69,7 +76,7 @@ bool CGUIModalScreen::OnEvent(SEvent event) IGUIElement::OnEvent(event); - return true; // absorb everything + return true; // absorb everything else } diff --git a/source/Irrlicht/CGUIWindow.cpp b/source/Irrlicht/CGUIWindow.cpp index ba706cf3..c8f7dec2 100644 --- a/source/Irrlicht/CGUIWindow.cpp +++ b/source/Irrlicht/CGUIWindow.cpp @@ -131,8 +131,28 @@ bool CGUIWindow::OnEvent(SEvent event) { if (event.GUIEvent.Caller == CloseButton) { - remove(); - return true; + if (Parent) + { + // send close event to parent + SEvent e; + e.EventType = EET_GUI_EVENT; + e.GUIEvent.Caller = this; + e.GUIEvent.Element = 0; + e.GUIEvent.EventType = EGET_ELEMENT_CLOSED; + + // if the event was not absorbed + if (!Parent->OnEvent(e)) + { + remove(); + } + return true; + + } + else + { + remove(); + return true; + } } } break; diff --git a/source/Irrlicht/Irrlicht8.0.vcproj b/source/Irrlicht/Irrlicht8.0.vcproj index ef86c61d..f8622339 100644 --- a/source/Irrlicht/Irrlicht8.0.vcproj +++ b/source/Irrlicht/Irrlicht8.0.vcproj @@ -78,7 +78,7 @@ Name="VCLinkerTool" UseLibraryDependencyInputs="true" AdditionalOptions="/MACHINE:I386" - AdditionalDependencies="kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib glu32.lib opengl32.lib" + AdditionalDependencies="kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib glu32.lib opengl32.lib" OutputFile="..\..\bin\Win32-visualstudio\Irrlicht.dll" LinkIncremental="2" SuppressStartupBanner="true" @@ -587,6 +587,14 @@ RelativePath=".\CParticleSphereEmitter.cpp" > + + + + diff --git a/tools/GUIEditor/CGUIEditWindow.cpp b/tools/GUIEditor/CGUIEditWindow.cpp index 5bb2d41e..5ba1ecc8 100644 --- a/tools/GUIEditor/CGUIEditWindow.cpp +++ b/tools/GUIEditor/CGUIEditWindow.cpp @@ -84,7 +84,12 @@ CGUIEditWindow::CGUIEditWindow(IGUIEnvironment* environment, core::rect rec AttribEditor->setRelativePosition( core::rect(0.0f, 0.0f, 1.0f, 1.0f)); AttribEditor->setAlignment(EGUIA_UPPERLEFT, EGUIA_LOWERRIGHT, EGUIA_UPPERLEFT, EGUIA_LOWERRIGHT); - ResizeButton = environment->addStaticText(L"/",core::rect(199-th,449-th,199,449), true, false, this, true); + ResizeButton = environment->addButton(core::rect(199-th,449-th,199,449), this); + ResizeButton->setDrawBorder(false); + ResizeButton->setEnabled(false); + ResizeButton->setSpriteBank(skin->getSpriteBank()); + ResizeButton->setSprite(EGBS_BUTTON_UP, skin->getIcon(EGDI_WINDOW_RESIZE), skin->getColor(EGDC_WINDOW_SYMBOL)); + ResizeButton->setSprite(EGBS_BUTTON_DOWN, skin->getIcon(EGDI_WINDOW_RESIZE), skin->getColor(EGDC_WINDOW_SYMBOL)); ResizeButton->grab(); ResizeButton->setSubElement(true); ResizeButton->setAlignment(EGUIA_LOWERRIGHT, EGUIA_LOWERRIGHT, EGUIA_LOWERRIGHT, EGUIA_LOWERRIGHT); diff --git a/tools/GUIEditor/CGUIEditWindow.h b/tools/GUIEditor/CGUIEditWindow.h index 1227413e..04bc5f19 100644 --- a/tools/GUIEditor/CGUIEditWindow.h +++ b/tools/GUIEditor/CGUIEditWindow.h @@ -4,7 +4,8 @@ #include "IGUIWindow.h" #include "CGUIAttributeEditor.h" -#include "IGUIStaticText.h" +//#include "IGUIStaticText.h" +#include "IGUIButton.h" #include "irrArray.h" #include "IAttributes.h" @@ -46,16 +47,16 @@ namespace gui // for dragging the window - bool Dragging; - bool Resizing; - core::position2d DragStart; + bool Dragging; + bool Resizing; + core::position2d DragStart; - IGUIElement* SelectedElement; // current selected element + IGUIElement* SelectedElement; // current selected element - CGUIAttributeEditor* AttribEditor; // edits the current attribute - CGUIAttributeEditor* OptionEditor; // edits the options for the window - CGUIAttributeEditor* EnvEditor; // edits attributes for the environment - IGUIStaticText* ResizeButton; + CGUIAttributeEditor* AttribEditor; // edits the current attribute + CGUIAttributeEditor* OptionEditor; // edits the options for the window + CGUIAttributeEditor* EnvEditor; // edits attributes for the environment + IGUIButton* ResizeButton; }; diff --git a/tools/GUIEditor/main.cpp b/tools/GUIEditor/main.cpp index 1370330c..af848937 100644 --- a/tools/GUIEditor/main.cpp +++ b/tools/GUIEditor/main.cpp @@ -70,6 +70,8 @@ int main() now we add the GUI Editor Workspace */ + env->loadGUI("c:\\out.xml"); + env->addGUIElement("GUIEditor"); while(device->run())