From 959831f4ef5a3e797f576c3de08cd65032c997ad Mon Sep 17 00:00:00 2001 From: David Walter Seikel Date: Sun, 13 Jan 2013 18:54:10 +1000 Subject: Remove damned ancient DOS line endings from Irrlicht. Hopefully I did not go overboard. --- .../source/Irrlicht/CGUIContextMenu.cpp | 1738 ++++++++++---------- 1 file changed, 869 insertions(+), 869 deletions(-) (limited to 'libraries/irrlicht-1.8/source/Irrlicht/CGUIContextMenu.cpp') diff --git a/libraries/irrlicht-1.8/source/Irrlicht/CGUIContextMenu.cpp b/libraries/irrlicht-1.8/source/Irrlicht/CGUIContextMenu.cpp index 67631e7..b6f5b79 100644 --- a/libraries/irrlicht-1.8/source/Irrlicht/CGUIContextMenu.cpp +++ b/libraries/irrlicht-1.8/source/Irrlicht/CGUIContextMenu.cpp @@ -1,869 +1,869 @@ -// 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 "CGUIContextMenu.h" - -#ifdef _IRR_COMPILE_WITH_GUI_ - -#include "IGUISkin.h" -#include "IGUIEnvironment.h" -#include "IVideoDriver.h" -#include "IGUIFont.h" -#include "IGUISpriteBank.h" -#include "os.h" - -namespace irr -{ -namespace gui -{ - - -//! constructor -CGUIContextMenu::CGUIContextMenu(IGUIEnvironment* environment, - IGUIElement* parent, s32 id, - core::rect rectangle, bool getFocus, bool allowFocus) - : IGUIContextMenu(environment, parent, id, rectangle), EventParent(0), LastFont(0), - CloseHandling(ECMC_REMOVE), HighLighted(-1), ChangeTime(0), AllowFocus(allowFocus) -{ - #ifdef _DEBUG - setDebugName("CGUIContextMenu"); - #endif - - Pos = rectangle.UpperLeftCorner; - recalculateSize(); - - if (getFocus) - Environment->setFocus(this); - - setNotClipped(true); -} - - -//! destructor -CGUIContextMenu::~CGUIContextMenu() -{ - for (u32 i=0; idrop(); - - if (LastFont) - LastFont->drop(); -} - -//! set behavior when menus are closed -void CGUIContextMenu::setCloseHandling(ECONTEXT_MENU_CLOSE onClose) -{ - CloseHandling = onClose; -} - -//! get current behavior when the menue will be closed -ECONTEXT_MENU_CLOSE CGUIContextMenu::getCloseHandling() const -{ - return CloseHandling; -} - -//! Returns amount of menu items -u32 CGUIContextMenu::getItemCount() const -{ - return Items.size(); -} - - -//! Adds a menu item. -u32 CGUIContextMenu::addItem(const wchar_t* text, s32 commandId, bool enabled, bool hasSubMenu, bool checked, bool autoChecking) -{ - return insertItem(Items.size(), text, commandId, enabled, hasSubMenu, checked, autoChecking); -} - -//! Insert a menu item at specified position. -u32 CGUIContextMenu::insertItem(u32 idx, const wchar_t* text, s32 commandId, bool enabled, - bool hasSubMenu, bool checked, bool autoChecking) -{ - SItem s; - s.Enabled = enabled; - s.Checked = checked; - s.AutoChecking = autoChecking; - s.Text = text; - s.IsSeparator = (text == 0); - s.SubMenu = 0; - s.CommandId = commandId; - - if (hasSubMenu) - { - s.SubMenu = new CGUIContextMenu(Environment, this, commandId, - core::rect(0,0,100,100), false, false); - s.SubMenu->setVisible(false); - } - - u32 result = idx; - if ( idx < Items.size() ) - { - Items.insert(s, idx); - } - else - { - Items.push_back(s); - result = Items.size() - 1; - } - - recalculateSize(); - return result; -} - -s32 CGUIContextMenu::findItemWithCommandId(s32 commandId, u32 idxStartSearch) const -{ - for ( u32 i=idxStartSearch; i= Items.size()) - return; - - if (menu) - menu->grab(); - if (Items[index].SubMenu) - Items[index].SubMenu->drop(); - - Items[index].SubMenu = menu; - menu->setVisible(false); - - if (Items[index].SubMenu) - { - menu->AllowFocus = false; - if ( Environment->getFocus() == menu ) - { - Environment->setFocus( this ); - } - } - - recalculateSize(); -} - - -//! Adds a separator item to the menu -void CGUIContextMenu::addSeparator() -{ - addItem(0, -1, true, false, false, false); -} - - -//! Returns text of the menu item. -const wchar_t* CGUIContextMenu::getItemText(u32 idx) const -{ - if (idx >= Items.size()) - return 0; - - return Items[idx].Text.c_str(); -} - - -//! Sets text of the menu item. -void CGUIContextMenu::setItemText(u32 idx, const wchar_t* text) -{ - if (idx >= Items.size()) - return; - - Items[idx].Text = text; - recalculateSize(); -} - -//! should the element change the checked status on clicking -void CGUIContextMenu::setItemAutoChecking(u32 idx, bool autoChecking) -{ - if ( idx >= Items.size()) - return; - - Items[idx].AutoChecking = autoChecking; -} - -//! does the element change the checked status on clicking -bool CGUIContextMenu::getItemAutoChecking(u32 idx) const -{ - if (idx >= Items.size()) - return false; - - return Items[idx].AutoChecking; -} - - -//! Returns if a menu item is enabled -bool CGUIContextMenu::isItemEnabled(u32 idx) const -{ - if (idx >= Items.size()) - { - _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; - return false; - } - - _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; - return Items[idx].Enabled; -} - - -//! Returns if a menu item is checked -bool CGUIContextMenu::isItemChecked(u32 idx) const -{ - if (idx >= Items.size()) - { - _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; - return false; - } - - _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; - return Items[idx].Checked; -} - - -//! Sets if the menu item should be enabled. -void CGUIContextMenu::setItemEnabled(u32 idx, bool enabled) -{ - if (idx >= Items.size()) - return; - - Items[idx].Enabled = enabled; -} - - -//! Sets if the menu item should be checked. -void CGUIContextMenu::setItemChecked(u32 idx, bool checked ) -{ - if (idx >= Items.size()) - return; - - Items[idx].Checked = checked; -} - - -//! Removes a menu item -void CGUIContextMenu::removeItem(u32 idx) -{ - if (idx >= Items.size()) - return; - - if (Items[idx].SubMenu) - { - Items[idx].SubMenu->drop(); - Items[idx].SubMenu = 0; - } - - Items.erase(idx); - recalculateSize(); -} - - -//! Removes all menu items -void CGUIContextMenu::removeAllItems() -{ - for (u32 i=0; idrop(); - - Items.clear(); - recalculateSize(); -} - - -//! called if an event happened. -bool CGUIContextMenu::OnEvent(const SEvent& event) -{ - if (isEnabled()) - { - - switch(event.EventType) - { - case EET_GUI_EVENT: - switch(event.GUIEvent.EventType) - { - case EGET_ELEMENT_FOCUS_LOST: - if (event.GUIEvent.Caller == this && !isMyChild(event.GUIEvent.Element) && AllowFocus) - { - // set event parent of submenus - IGUIElement * p = EventParent ? EventParent : Parent; - setEventParent(p); - - SEvent event; - event.EventType = EET_GUI_EVENT; - event.GUIEvent.Caller = this; - event.GUIEvent.Element = 0; - event.GUIEvent.EventType = EGET_ELEMENT_CLOSED; - if ( !p->OnEvent(event) ) - { - if ( CloseHandling & ECMC_HIDE ) - { - setVisible(false); - } - if ( CloseHandling & ECMC_REMOVE ) - { - remove(); - } - } - - return false; - } - break; - case EGET_ELEMENT_FOCUSED: - if (event.GUIEvent.Caller == this && !AllowFocus) - { - return true; - } - break; - default: - break; - } - break; - case EET_MOUSE_INPUT_EVENT: - switch(event.MouseInput.Event) - { - case EMIE_LMOUSE_LEFT_UP: - { - // menu might be removed if it loses focus in sendClick, so grab a reference - grab(); - const u32 t = sendClick(core::position2d(event.MouseInput.X, event.MouseInput.Y)); - if ((t==0 || t==1) && Environment->hasFocus(this)) - Environment->removeFocus(this); - drop(); - } - return true; - case EMIE_LMOUSE_PRESSED_DOWN: - return true; - case EMIE_MOUSE_MOVED: - if (Environment->hasFocus(this)) - highlight(core::position2d(event.MouseInput.X, event.MouseInput.Y), true); - return true; - default: - break; - } - break; - default: - break; - } - } - - return IGUIElement::OnEvent(event); -} - - -//! Sets the visible state of this element. -void CGUIContextMenu::setVisible(bool visible) -{ - HighLighted = -1; - ChangeTime = os::Timer::getTime(); - for (u32 j=0; jsetVisible(false); - - IGUIElement::setVisible(visible); -} - - -//! sends a click Returns: -//! 0 if click went outside of the element, -//! 1 if a valid button was clicked, -//! 2 if a nonclickable element was clicked -u32 CGUIContextMenu::sendClick(const core::position2d& p) -{ - u32 t = 0; - - // get number of open submenu - s32 openmenu = -1; - s32 j; - for (j=0; j<(s32)Items.size(); ++j) - if (Items[j].SubMenu && Items[j].SubMenu->isVisible()) - { - openmenu = j; - break; - } - - // delegate click operation to submenu - if (openmenu != -1) - { - t = Items[j].SubMenu->sendClick(p); - if (t != 0) - return t; // clicked something - } - - // check click on myself - if (isPointInside(p) && - (u32)HighLighted < Items.size()) - { - if (!Items[HighLighted].Enabled || - Items[HighLighted].IsSeparator || - Items[HighLighted].SubMenu) - return 2; - - if ( Items[HighLighted].AutoChecking ) - { - Items[HighLighted].Checked = Items[HighLighted].Checked ? false : true; - } - - SEvent event; - event.EventType = EET_GUI_EVENT; - event.GUIEvent.Caller = this; - event.GUIEvent.Element = 0; - event.GUIEvent.EventType = EGET_MENU_ITEM_SELECTED; - if (EventParent) - EventParent->OnEvent(event); - else if (Parent) - Parent->OnEvent(event); - - return 1; - } - - return 0; -} - - -//! returns true, if an element was highligted -bool CGUIContextMenu::highlight(const core::position2d& p, bool canOpenSubMenu) -{ - if (!isEnabled()) - { - return false; - } - - // get number of open submenu - s32 openmenu = -1; - s32 i; - for (i=0; i<(s32)Items.size(); ++i) - if (Items[i].Enabled && Items[i].SubMenu && Items[i].SubMenu->isVisible()) - { - openmenu = i; - break; - } - - // delegate highlight operation to submenu - if (openmenu != -1) - { - if (Items[openmenu].Enabled && Items[openmenu].SubMenu->highlight(p, canOpenSubMenu)) - { - HighLighted = openmenu; - ChangeTime = os::Timer::getTime(); - return true; - } - } - - // highlight myself - for (i=0; i<(s32)Items.size(); ++i) - { - if (Items[i].Enabled && getHRect(Items[i], AbsoluteRect).isPointInside(p)) - { - HighLighted = i; - ChangeTime = os::Timer::getTime(); - - // make submenus visible/invisible - for (s32 j=0; j<(s32)Items.size(); ++j) - if (Items[j].SubMenu) - { - if ( j == i && canOpenSubMenu && Items[j].Enabled ) - Items[j].SubMenu->setVisible(true); - else if ( j != i ) - Items[j].SubMenu->setVisible(false); - } - return true; - } - } - - HighLighted = openmenu; - return false; -} - - -//! returns the item highlight-area -core::rect CGUIContextMenu::getHRect(const SItem& i, const core::rect& absolute) const -{ - core::rect r = absolute; - r.UpperLeftCorner.Y += i.PosY; - r.LowerRightCorner.Y = r.UpperLeftCorner.Y + i.Dim.Height; - return r; -} - - -//! Gets drawing rect of Item -core::rect CGUIContextMenu::getRect(const SItem& i, const core::rect& absolute) const -{ - core::rect r = absolute; - r.UpperLeftCorner.Y += i.PosY; - r.LowerRightCorner.Y = r.UpperLeftCorner.Y + i.Dim.Height; - r.UpperLeftCorner.X += 20; - return r; -} - - -//! draws the element and its children -void CGUIContextMenu::draw() -{ - if (!IsVisible) - return; - - IGUISkin* skin = Environment->getSkin(); - - if (!skin) - return; - - IGUIFont* font = skin->getFont(EGDF_MENU); - if (font != LastFont) - { - if (LastFont) - LastFont->drop(); - LastFont = font; - if (LastFont) - LastFont->grab(); - - recalculateSize(); - } - - IGUISpriteBank* sprites = skin->getSpriteBank(); - - core::rect rect = AbsoluteRect; - core::rect* clip = 0; - - // draw frame - skin->draw3DMenuPane(this, AbsoluteRect, clip); - - // loop through all menu items - - rect = AbsoluteRect; - s32 y = AbsoluteRect.UpperLeftCorner.Y; - - for (s32 i=0; i<(s32)Items.size(); ++i) - { - if (Items[i].IsSeparator) - { - // draw separator - rect = AbsoluteRect; - rect.UpperLeftCorner.Y += Items[i].PosY + 3; - rect.LowerRightCorner.Y = rect.UpperLeftCorner.Y + 1; - rect.UpperLeftCorner.X += 5; - rect.LowerRightCorner.X -= 5; - skin->draw2DRectangle(this, skin->getColor(EGDC_3D_SHADOW), rect, clip); - - rect.LowerRightCorner.Y += 1; - rect.UpperLeftCorner.Y += 1; - skin->draw2DRectangle(this, skin->getColor(EGDC_3D_HIGH_LIGHT), rect, clip); - - y += 10; - } - else - { - rect = getRect(Items[i], AbsoluteRect); - - // draw highlighted - - if (i == HighLighted && Items[i].Enabled) - { - core::rect r = AbsoluteRect; - r.LowerRightCorner.Y = rect.LowerRightCorner.Y; - r.UpperLeftCorner.Y = rect.UpperLeftCorner.Y; - r.LowerRightCorner.X -= 5; - r.UpperLeftCorner.X += 5; - skin->draw2DRectangle(this, skin->getColor(EGDC_HIGH_LIGHT), r, clip); - } - - // draw text - - EGUI_DEFAULT_COLOR c = EGDC_BUTTON_TEXT; - - if (i == HighLighted) - c = EGDC_HIGH_LIGHT_TEXT; - - if (!Items[i].Enabled) - c = EGDC_GRAY_TEXT; - - if (font) - font->draw(Items[i].Text.c_str(), rect, - skin->getColor(c), false, true, clip); - - // draw submenu symbol - if (Items[i].SubMenu && sprites) - { - core::rect r = rect; - r.UpperLeftCorner.X = r.LowerRightCorner.X - 15; - - sprites->draw2DSprite(skin->getIcon(EGDI_CURSOR_RIGHT), - r.getCenter(), clip, skin->getColor(c), - (i == HighLighted) ? ChangeTime : 0, - (i == HighLighted) ? os::Timer::getTime() : 0, - (i == HighLighted), true); - } - - // draw checked symbol - if (Items[i].Checked && sprites) - { - 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, - (i == HighLighted) ? os::Timer::getTime() : 0, - (i == HighLighted), true); - } - } - } - - IGUIElement::draw(); -} - - -void CGUIContextMenu::recalculateSize() -{ - IGUIFont* font = Environment->getSkin()->getFont(EGDF_MENU); - - if (!font) - return; - - core::rect rect; - rect.UpperLeftCorner = RelativeRect.UpperLeftCorner; - u32 width = 100; - u32 height = 3; - - u32 i; - for (i=0; igetDimension(Items[i].Text.c_str()); - Items[i].Dim.Width += 40; - - if (Items[i].Dim.Width > width) - width = Items[i].Dim.Width; - } - - Items[i].PosY = height; - height += Items[i].Dim.Height; - } - - height += 5; - - if (height < 10) - height = 10; - - rect.LowerRightCorner.X = RelativeRect.UpperLeftCorner.X + width; - rect.LowerRightCorner.Y = RelativeRect.UpperLeftCorner.Y + height; - - setRelativePosition(rect); - - // recalculate submenus - for (i=0; igetAbsolutePosition().getWidth(); - const s32 h = Items[i].SubMenu->getAbsolutePosition().getHeight(); - - core::rect subRect(width-5, Items[i].PosY, width+w-5, Items[i].PosY+h); - - // if it would be drawn beyond the right border, then add it to the left side - gui::IGUIElement * root = Environment->getRootGUIElement(); - if ( root ) - { - core::rect rectRoot( root->getAbsolutePosition() ); - if ( getAbsolutePosition().UpperLeftCorner.X+subRect.LowerRightCorner.X > rectRoot.LowerRightCorner.X ) - { - subRect.UpperLeftCorner.X = -w; - subRect.LowerRightCorner.X = 0; - } - } - - Items[i].SubMenu->setRelativePosition(subRect); - } - } -} - - -//! Returns the selected item in the menu -s32 CGUIContextMenu::getSelectedItem() const -{ - return HighLighted; -} - - -//! \return Returns a pointer to the submenu of an item. -IGUIContextMenu* CGUIContextMenu::getSubMenu(u32 idx) const -{ - if (idx >= Items.size()) - return 0; - - return Items[idx].SubMenu; -} - - -//! Returns command id of a menu item -s32 CGUIContextMenu::getItemCommandId(u32 idx) const -{ - if (idx >= Items.size()) - return -1; - - return Items[idx].CommandId; -} - - -//! Sets the command id of a menu item -void CGUIContextMenu::setItemCommandId(u32 idx, s32 id) -{ - if (idx >= Items.size()) - return; - - Items[idx].CommandId = id; -} - - -//! Writes attributes of the element. -void CGUIContextMenu::serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options=0) const -{ - IGUIElement::serializeAttributes(out,options); - out->addPosition2d("Position", Pos); - - if (Parent->getType() == EGUIET_CONTEXT_MENU || Parent->getType() == EGUIET_MENU ) - { - const IGUIContextMenu* const ptr = (const IGUIContextMenu*)Parent; - // find the position of this item in its parent's list - u32 i; - // VC6 needs the cast for this - for (i=0; (igetItemCount()) && (ptr->getSubMenu(i) != (const IGUIContextMenu*)this); ++i) - ; // do nothing - - out->addInt("ParentItem", i); - } - - out->addInt("CloseHandling", (s32)CloseHandling); - - // write out the item list - out->addInt("ItemCount", Items.size()); - - core::stringc tmp; - - for (u32 i=0; i < Items.size(); ++i) - { - tmp = "IsSeparator"; tmp += i; - out->addBool(tmp.c_str(), Items[i].IsSeparator); - - if (!Items[i].IsSeparator) - { - tmp = "Text"; tmp += i; - out->addString(tmp.c_str(), Items[i].Text.c_str()); - tmp = "CommandID"; tmp += i; - out->addInt(tmp.c_str(), Items[i].CommandId); - tmp = "Enabled"; tmp += i; - out->addBool(tmp.c_str(), Items[i].Enabled); - tmp = "Checked"; tmp += i; - out->addBool(tmp.c_str(), Items[i].Checked); - tmp = "AutoChecking"; tmp += i; - out->addBool(tmp.c_str(), Items[i].AutoChecking); - } - } -} - - -//! Reads attributes of the element -void CGUIContextMenu::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options=0) -{ - IGUIElement::deserializeAttributes(in,options); - - Pos = in->getAttributeAsPosition2d("Position"); - - // link to this item's parent - if (Parent && ( Parent->getType() == EGUIET_CONTEXT_MENU || Parent->getType() == EGUIET_MENU ) ) - ((CGUIContextMenu*)Parent)->setSubMenu(in->getAttributeAsInt("ParentItem"),this); - - CloseHandling = (ECONTEXT_MENU_CLOSE)in->getAttributeAsInt("CloseHandling"); - - removeAllItems(); - - // read the item list - const s32 count = in->getAttributeAsInt("ItemCount"); - - for (s32 i=0; iexistsAttribute(tmp.c_str()) && in->getAttributeAsBool(tmp.c_str()) ) - addSeparator(); - else - { - tmp = "Text"; tmp += i; - if ( in->existsAttribute(tmp.c_str()) ) - txt = in->getAttributeAsStringW(tmp.c_str()); - - tmp = "CommandID"; tmp += i; - if ( in->existsAttribute(tmp.c_str()) ) - commandid = in->getAttributeAsInt(tmp.c_str()); - - tmp = "Enabled"; tmp += i; - if ( in->existsAttribute(tmp.c_str()) ) - enabled = in->getAttributeAsBool(tmp.c_str()); - - tmp = "Checked"; tmp += i; - if ( in->existsAttribute(tmp.c_str()) ) - checked = in->getAttributeAsBool(tmp.c_str()); - - tmp = "AutoChecking"; tmp += i; - if ( in->existsAttribute(tmp.c_str()) ) - autochecking = in->getAttributeAsBool(tmp.c_str()); - - addItem(core::stringw(txt.c_str()).c_str(), commandid, enabled, false, checked, autochecking); - } - } - - recalculateSize(); -} - - -// because sometimes the element has no parent at click time -void CGUIContextMenu::setEventParent(IGUIElement *parent) -{ - EventParent = parent; - - for (u32 i=0; isetEventParent(parent); -} - - -bool CGUIContextMenu::hasOpenSubMenu() const -{ - for (u32 i=0; iisVisible()) - return true; - - return false; -} - - -void CGUIContextMenu::closeAllSubMenus() -{ - for (u32 i=0; isetVisible(false); - - //HighLighted = -1; -} - - -} // end namespace -} // end namespace - -#endif // _IRR_COMPILE_WITH_GUI_ - +// 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 "CGUIContextMenu.h" + +#ifdef _IRR_COMPILE_WITH_GUI_ + +#include "IGUISkin.h" +#include "IGUIEnvironment.h" +#include "IVideoDriver.h" +#include "IGUIFont.h" +#include "IGUISpriteBank.h" +#include "os.h" + +namespace irr +{ +namespace gui +{ + + +//! constructor +CGUIContextMenu::CGUIContextMenu(IGUIEnvironment* environment, + IGUIElement* parent, s32 id, + core::rect rectangle, bool getFocus, bool allowFocus) + : IGUIContextMenu(environment, parent, id, rectangle), EventParent(0), LastFont(0), + CloseHandling(ECMC_REMOVE), HighLighted(-1), ChangeTime(0), AllowFocus(allowFocus) +{ + #ifdef _DEBUG + setDebugName("CGUIContextMenu"); + #endif + + Pos = rectangle.UpperLeftCorner; + recalculateSize(); + + if (getFocus) + Environment->setFocus(this); + + setNotClipped(true); +} + + +//! destructor +CGUIContextMenu::~CGUIContextMenu() +{ + for (u32 i=0; idrop(); + + if (LastFont) + LastFont->drop(); +} + +//! set behavior when menus are closed +void CGUIContextMenu::setCloseHandling(ECONTEXT_MENU_CLOSE onClose) +{ + CloseHandling = onClose; +} + +//! get current behavior when the menue will be closed +ECONTEXT_MENU_CLOSE CGUIContextMenu::getCloseHandling() const +{ + return CloseHandling; +} + +//! Returns amount of menu items +u32 CGUIContextMenu::getItemCount() const +{ + return Items.size(); +} + + +//! Adds a menu item. +u32 CGUIContextMenu::addItem(const wchar_t* text, s32 commandId, bool enabled, bool hasSubMenu, bool checked, bool autoChecking) +{ + return insertItem(Items.size(), text, commandId, enabled, hasSubMenu, checked, autoChecking); +} + +//! Insert a menu item at specified position. +u32 CGUIContextMenu::insertItem(u32 idx, const wchar_t* text, s32 commandId, bool enabled, + bool hasSubMenu, bool checked, bool autoChecking) +{ + SItem s; + s.Enabled = enabled; + s.Checked = checked; + s.AutoChecking = autoChecking; + s.Text = text; + s.IsSeparator = (text == 0); + s.SubMenu = 0; + s.CommandId = commandId; + + if (hasSubMenu) + { + s.SubMenu = new CGUIContextMenu(Environment, this, commandId, + core::rect(0,0,100,100), false, false); + s.SubMenu->setVisible(false); + } + + u32 result = idx; + if ( idx < Items.size() ) + { + Items.insert(s, idx); + } + else + { + Items.push_back(s); + result = Items.size() - 1; + } + + recalculateSize(); + return result; +} + +s32 CGUIContextMenu::findItemWithCommandId(s32 commandId, u32 idxStartSearch) const +{ + for ( u32 i=idxStartSearch; i= Items.size()) + return; + + if (menu) + menu->grab(); + if (Items[index].SubMenu) + Items[index].SubMenu->drop(); + + Items[index].SubMenu = menu; + menu->setVisible(false); + + if (Items[index].SubMenu) + { + menu->AllowFocus = false; + if ( Environment->getFocus() == menu ) + { + Environment->setFocus( this ); + } + } + + recalculateSize(); +} + + +//! Adds a separator item to the menu +void CGUIContextMenu::addSeparator() +{ + addItem(0, -1, true, false, false, false); +} + + +//! Returns text of the menu item. +const wchar_t* CGUIContextMenu::getItemText(u32 idx) const +{ + if (idx >= Items.size()) + return 0; + + return Items[idx].Text.c_str(); +} + + +//! Sets text of the menu item. +void CGUIContextMenu::setItemText(u32 idx, const wchar_t* text) +{ + if (idx >= Items.size()) + return; + + Items[idx].Text = text; + recalculateSize(); +} + +//! should the element change the checked status on clicking +void CGUIContextMenu::setItemAutoChecking(u32 idx, bool autoChecking) +{ + if ( idx >= Items.size()) + return; + + Items[idx].AutoChecking = autoChecking; +} + +//! does the element change the checked status on clicking +bool CGUIContextMenu::getItemAutoChecking(u32 idx) const +{ + if (idx >= Items.size()) + return false; + + return Items[idx].AutoChecking; +} + + +//! Returns if a menu item is enabled +bool CGUIContextMenu::isItemEnabled(u32 idx) const +{ + if (idx >= Items.size()) + { + _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; + return false; + } + + _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; + return Items[idx].Enabled; +} + + +//! Returns if a menu item is checked +bool CGUIContextMenu::isItemChecked(u32 idx) const +{ + if (idx >= Items.size()) + { + _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; + return false; + } + + _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; + return Items[idx].Checked; +} + + +//! Sets if the menu item should be enabled. +void CGUIContextMenu::setItemEnabled(u32 idx, bool enabled) +{ + if (idx >= Items.size()) + return; + + Items[idx].Enabled = enabled; +} + + +//! Sets if the menu item should be checked. +void CGUIContextMenu::setItemChecked(u32 idx, bool checked ) +{ + if (idx >= Items.size()) + return; + + Items[idx].Checked = checked; +} + + +//! Removes a menu item +void CGUIContextMenu::removeItem(u32 idx) +{ + if (idx >= Items.size()) + return; + + if (Items[idx].SubMenu) + { + Items[idx].SubMenu->drop(); + Items[idx].SubMenu = 0; + } + + Items.erase(idx); + recalculateSize(); +} + + +//! Removes all menu items +void CGUIContextMenu::removeAllItems() +{ + for (u32 i=0; idrop(); + + Items.clear(); + recalculateSize(); +} + + +//! called if an event happened. +bool CGUIContextMenu::OnEvent(const SEvent& event) +{ + if (isEnabled()) + { + + switch(event.EventType) + { + case EET_GUI_EVENT: + switch(event.GUIEvent.EventType) + { + case EGET_ELEMENT_FOCUS_LOST: + if (event.GUIEvent.Caller == this && !isMyChild(event.GUIEvent.Element) && AllowFocus) + { + // set event parent of submenus + IGUIElement * p = EventParent ? EventParent : Parent; + setEventParent(p); + + SEvent event; + event.EventType = EET_GUI_EVENT; + event.GUIEvent.Caller = this; + event.GUIEvent.Element = 0; + event.GUIEvent.EventType = EGET_ELEMENT_CLOSED; + if ( !p->OnEvent(event) ) + { + if ( CloseHandling & ECMC_HIDE ) + { + setVisible(false); + } + if ( CloseHandling & ECMC_REMOVE ) + { + remove(); + } + } + + return false; + } + break; + case EGET_ELEMENT_FOCUSED: + if (event.GUIEvent.Caller == this && !AllowFocus) + { + return true; + } + break; + default: + break; + } + break; + case EET_MOUSE_INPUT_EVENT: + switch(event.MouseInput.Event) + { + case EMIE_LMOUSE_LEFT_UP: + { + // menu might be removed if it loses focus in sendClick, so grab a reference + grab(); + const u32 t = sendClick(core::position2d(event.MouseInput.X, event.MouseInput.Y)); + if ((t==0 || t==1) && Environment->hasFocus(this)) + Environment->removeFocus(this); + drop(); + } + return true; + case EMIE_LMOUSE_PRESSED_DOWN: + return true; + case EMIE_MOUSE_MOVED: + if (Environment->hasFocus(this)) + highlight(core::position2d(event.MouseInput.X, event.MouseInput.Y), true); + return true; + default: + break; + } + break; + default: + break; + } + } + + return IGUIElement::OnEvent(event); +} + + +//! Sets the visible state of this element. +void CGUIContextMenu::setVisible(bool visible) +{ + HighLighted = -1; + ChangeTime = os::Timer::getTime(); + for (u32 j=0; jsetVisible(false); + + IGUIElement::setVisible(visible); +} + + +//! sends a click Returns: +//! 0 if click went outside of the element, +//! 1 if a valid button was clicked, +//! 2 if a nonclickable element was clicked +u32 CGUIContextMenu::sendClick(const core::position2d& p) +{ + u32 t = 0; + + // get number of open submenu + s32 openmenu = -1; + s32 j; + for (j=0; j<(s32)Items.size(); ++j) + if (Items[j].SubMenu && Items[j].SubMenu->isVisible()) + { + openmenu = j; + break; + } + + // delegate click operation to submenu + if (openmenu != -1) + { + t = Items[j].SubMenu->sendClick(p); + if (t != 0) + return t; // clicked something + } + + // check click on myself + if (isPointInside(p) && + (u32)HighLighted < Items.size()) + { + if (!Items[HighLighted].Enabled || + Items[HighLighted].IsSeparator || + Items[HighLighted].SubMenu) + return 2; + + if ( Items[HighLighted].AutoChecking ) + { + Items[HighLighted].Checked = Items[HighLighted].Checked ? false : true; + } + + SEvent event; + event.EventType = EET_GUI_EVENT; + event.GUIEvent.Caller = this; + event.GUIEvent.Element = 0; + event.GUIEvent.EventType = EGET_MENU_ITEM_SELECTED; + if (EventParent) + EventParent->OnEvent(event); + else if (Parent) + Parent->OnEvent(event); + + return 1; + } + + return 0; +} + + +//! returns true, if an element was highligted +bool CGUIContextMenu::highlight(const core::position2d& p, bool canOpenSubMenu) +{ + if (!isEnabled()) + { + return false; + } + + // get number of open submenu + s32 openmenu = -1; + s32 i; + for (i=0; i<(s32)Items.size(); ++i) + if (Items[i].Enabled && Items[i].SubMenu && Items[i].SubMenu->isVisible()) + { + openmenu = i; + break; + } + + // delegate highlight operation to submenu + if (openmenu != -1) + { + if (Items[openmenu].Enabled && Items[openmenu].SubMenu->highlight(p, canOpenSubMenu)) + { + HighLighted = openmenu; + ChangeTime = os::Timer::getTime(); + return true; + } + } + + // highlight myself + for (i=0; i<(s32)Items.size(); ++i) + { + if (Items[i].Enabled && getHRect(Items[i], AbsoluteRect).isPointInside(p)) + { + HighLighted = i; + ChangeTime = os::Timer::getTime(); + + // make submenus visible/invisible + for (s32 j=0; j<(s32)Items.size(); ++j) + if (Items[j].SubMenu) + { + if ( j == i && canOpenSubMenu && Items[j].Enabled ) + Items[j].SubMenu->setVisible(true); + else if ( j != i ) + Items[j].SubMenu->setVisible(false); + } + return true; + } + } + + HighLighted = openmenu; + return false; +} + + +//! returns the item highlight-area +core::rect CGUIContextMenu::getHRect(const SItem& i, const core::rect& absolute) const +{ + core::rect r = absolute; + r.UpperLeftCorner.Y += i.PosY; + r.LowerRightCorner.Y = r.UpperLeftCorner.Y + i.Dim.Height; + return r; +} + + +//! Gets drawing rect of Item +core::rect CGUIContextMenu::getRect(const SItem& i, const core::rect& absolute) const +{ + core::rect r = absolute; + r.UpperLeftCorner.Y += i.PosY; + r.LowerRightCorner.Y = r.UpperLeftCorner.Y + i.Dim.Height; + r.UpperLeftCorner.X += 20; + return r; +} + + +//! draws the element and its children +void CGUIContextMenu::draw() +{ + if (!IsVisible) + return; + + IGUISkin* skin = Environment->getSkin(); + + if (!skin) + return; + + IGUIFont* font = skin->getFont(EGDF_MENU); + if (font != LastFont) + { + if (LastFont) + LastFont->drop(); + LastFont = font; + if (LastFont) + LastFont->grab(); + + recalculateSize(); + } + + IGUISpriteBank* sprites = skin->getSpriteBank(); + + core::rect rect = AbsoluteRect; + core::rect* clip = 0; + + // draw frame + skin->draw3DMenuPane(this, AbsoluteRect, clip); + + // loop through all menu items + + rect = AbsoluteRect; + s32 y = AbsoluteRect.UpperLeftCorner.Y; + + for (s32 i=0; i<(s32)Items.size(); ++i) + { + if (Items[i].IsSeparator) + { + // draw separator + rect = AbsoluteRect; + rect.UpperLeftCorner.Y += Items[i].PosY + 3; + rect.LowerRightCorner.Y = rect.UpperLeftCorner.Y + 1; + rect.UpperLeftCorner.X += 5; + rect.LowerRightCorner.X -= 5; + skin->draw2DRectangle(this, skin->getColor(EGDC_3D_SHADOW), rect, clip); + + rect.LowerRightCorner.Y += 1; + rect.UpperLeftCorner.Y += 1; + skin->draw2DRectangle(this, skin->getColor(EGDC_3D_HIGH_LIGHT), rect, clip); + + y += 10; + } + else + { + rect = getRect(Items[i], AbsoluteRect); + + // draw highlighted + + if (i == HighLighted && Items[i].Enabled) + { + core::rect r = AbsoluteRect; + r.LowerRightCorner.Y = rect.LowerRightCorner.Y; + r.UpperLeftCorner.Y = rect.UpperLeftCorner.Y; + r.LowerRightCorner.X -= 5; + r.UpperLeftCorner.X += 5; + skin->draw2DRectangle(this, skin->getColor(EGDC_HIGH_LIGHT), r, clip); + } + + // draw text + + EGUI_DEFAULT_COLOR c = EGDC_BUTTON_TEXT; + + if (i == HighLighted) + c = EGDC_HIGH_LIGHT_TEXT; + + if (!Items[i].Enabled) + c = EGDC_GRAY_TEXT; + + if (font) + font->draw(Items[i].Text.c_str(), rect, + skin->getColor(c), false, true, clip); + + // draw submenu symbol + if (Items[i].SubMenu && sprites) + { + core::rect r = rect; + r.UpperLeftCorner.X = r.LowerRightCorner.X - 15; + + sprites->draw2DSprite(skin->getIcon(EGDI_CURSOR_RIGHT), + r.getCenter(), clip, skin->getColor(c), + (i == HighLighted) ? ChangeTime : 0, + (i == HighLighted) ? os::Timer::getTime() : 0, + (i == HighLighted), true); + } + + // draw checked symbol + if (Items[i].Checked && sprites) + { + 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, + (i == HighLighted) ? os::Timer::getTime() : 0, + (i == HighLighted), true); + } + } + } + + IGUIElement::draw(); +} + + +void CGUIContextMenu::recalculateSize() +{ + IGUIFont* font = Environment->getSkin()->getFont(EGDF_MENU); + + if (!font) + return; + + core::rect rect; + rect.UpperLeftCorner = RelativeRect.UpperLeftCorner; + u32 width = 100; + u32 height = 3; + + u32 i; + for (i=0; igetDimension(Items[i].Text.c_str()); + Items[i].Dim.Width += 40; + + if (Items[i].Dim.Width > width) + width = Items[i].Dim.Width; + } + + Items[i].PosY = height; + height += Items[i].Dim.Height; + } + + height += 5; + + if (height < 10) + height = 10; + + rect.LowerRightCorner.X = RelativeRect.UpperLeftCorner.X + width; + rect.LowerRightCorner.Y = RelativeRect.UpperLeftCorner.Y + height; + + setRelativePosition(rect); + + // recalculate submenus + for (i=0; igetAbsolutePosition().getWidth(); + const s32 h = Items[i].SubMenu->getAbsolutePosition().getHeight(); + + core::rect subRect(width-5, Items[i].PosY, width+w-5, Items[i].PosY+h); + + // if it would be drawn beyond the right border, then add it to the left side + gui::IGUIElement * root = Environment->getRootGUIElement(); + if ( root ) + { + core::rect rectRoot( root->getAbsolutePosition() ); + if ( getAbsolutePosition().UpperLeftCorner.X+subRect.LowerRightCorner.X > rectRoot.LowerRightCorner.X ) + { + subRect.UpperLeftCorner.X = -w; + subRect.LowerRightCorner.X = 0; + } + } + + Items[i].SubMenu->setRelativePosition(subRect); + } + } +} + + +//! Returns the selected item in the menu +s32 CGUIContextMenu::getSelectedItem() const +{ + return HighLighted; +} + + +//! \return Returns a pointer to the submenu of an item. +IGUIContextMenu* CGUIContextMenu::getSubMenu(u32 idx) const +{ + if (idx >= Items.size()) + return 0; + + return Items[idx].SubMenu; +} + + +//! Returns command id of a menu item +s32 CGUIContextMenu::getItemCommandId(u32 idx) const +{ + if (idx >= Items.size()) + return -1; + + return Items[idx].CommandId; +} + + +//! Sets the command id of a menu item +void CGUIContextMenu::setItemCommandId(u32 idx, s32 id) +{ + if (idx >= Items.size()) + return; + + Items[idx].CommandId = id; +} + + +//! Writes attributes of the element. +void CGUIContextMenu::serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options=0) const +{ + IGUIElement::serializeAttributes(out,options); + out->addPosition2d("Position", Pos); + + if (Parent->getType() == EGUIET_CONTEXT_MENU || Parent->getType() == EGUIET_MENU ) + { + const IGUIContextMenu* const ptr = (const IGUIContextMenu*)Parent; + // find the position of this item in its parent's list + u32 i; + // VC6 needs the cast for this + for (i=0; (igetItemCount()) && (ptr->getSubMenu(i) != (const IGUIContextMenu*)this); ++i) + ; // do nothing + + out->addInt("ParentItem", i); + } + + out->addInt("CloseHandling", (s32)CloseHandling); + + // write out the item list + out->addInt("ItemCount", Items.size()); + + core::stringc tmp; + + for (u32 i=0; i < Items.size(); ++i) + { + tmp = "IsSeparator"; tmp += i; + out->addBool(tmp.c_str(), Items[i].IsSeparator); + + if (!Items[i].IsSeparator) + { + tmp = "Text"; tmp += i; + out->addString(tmp.c_str(), Items[i].Text.c_str()); + tmp = "CommandID"; tmp += i; + out->addInt(tmp.c_str(), Items[i].CommandId); + tmp = "Enabled"; tmp += i; + out->addBool(tmp.c_str(), Items[i].Enabled); + tmp = "Checked"; tmp += i; + out->addBool(tmp.c_str(), Items[i].Checked); + tmp = "AutoChecking"; tmp += i; + out->addBool(tmp.c_str(), Items[i].AutoChecking); + } + } +} + + +//! Reads attributes of the element +void CGUIContextMenu::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options=0) +{ + IGUIElement::deserializeAttributes(in,options); + + Pos = in->getAttributeAsPosition2d("Position"); + + // link to this item's parent + if (Parent && ( Parent->getType() == EGUIET_CONTEXT_MENU || Parent->getType() == EGUIET_MENU ) ) + ((CGUIContextMenu*)Parent)->setSubMenu(in->getAttributeAsInt("ParentItem"),this); + + CloseHandling = (ECONTEXT_MENU_CLOSE)in->getAttributeAsInt("CloseHandling"); + + removeAllItems(); + + // read the item list + const s32 count = in->getAttributeAsInt("ItemCount"); + + for (s32 i=0; iexistsAttribute(tmp.c_str()) && in->getAttributeAsBool(tmp.c_str()) ) + addSeparator(); + else + { + tmp = "Text"; tmp += i; + if ( in->existsAttribute(tmp.c_str()) ) + txt = in->getAttributeAsStringW(tmp.c_str()); + + tmp = "CommandID"; tmp += i; + if ( in->existsAttribute(tmp.c_str()) ) + commandid = in->getAttributeAsInt(tmp.c_str()); + + tmp = "Enabled"; tmp += i; + if ( in->existsAttribute(tmp.c_str()) ) + enabled = in->getAttributeAsBool(tmp.c_str()); + + tmp = "Checked"; tmp += i; + if ( in->existsAttribute(tmp.c_str()) ) + checked = in->getAttributeAsBool(tmp.c_str()); + + tmp = "AutoChecking"; tmp += i; + if ( in->existsAttribute(tmp.c_str()) ) + autochecking = in->getAttributeAsBool(tmp.c_str()); + + addItem(core::stringw(txt.c_str()).c_str(), commandid, enabled, false, checked, autochecking); + } + } + + recalculateSize(); +} + + +// because sometimes the element has no parent at click time +void CGUIContextMenu::setEventParent(IGUIElement *parent) +{ + EventParent = parent; + + for (u32 i=0; isetEventParent(parent); +} + + +bool CGUIContextMenu::hasOpenSubMenu() const +{ + for (u32 i=0; iisVisible()) + return true; + + return false; +} + + +void CGUIContextMenu::closeAllSubMenus() +{ + for (u32 i=0; isetVisible(false); + + //HighLighted = -1; +} + + +} // end namespace +} // end namespace + +#endif // _IRR_COMPILE_WITH_GUI_ + -- cgit v1.1