Commit 387f910c authored by cutealien's avatar cutealien

New contextmenue features:

- automatic checking for checked flag.
- close handling now customizable
- serialization can handle incomplete xml's
- setEventParent now in public interface
- New function findItemWithCommandId.
- New function insertItem


git-svn-id: svn://svn.code.sf.net/p/irrlicht/code/trunk@2771 dfc29bdd-3216-0410-991c-e03cc46cb475
parent d12a0027
...@@ -11,6 +11,21 @@ namespace irr ...@@ -11,6 +11,21 @@ namespace irr
{ {
namespace gui namespace gui
{ {
//! Close behaviour.
//! Default is ECMC_REMOVE
enum ECONTEXT_MENU_CLOSE
{
//! do nothing - menu stays open
ECMC_IGNORE = 0,
//! remove the gui element
ECMC_REMOVE = 1,
//! call setVisible(false)
ECMC_HIDE = 2,
// note to implementors - this is planned as bitset, so continue with 4 if you need to add further flags.
};
//! GUI Context menu interface. //! GUI Context menu interface.
class IGUIContextMenu : public IGUIElement class IGUIContextMenu : public IGUIElement
...@@ -21,6 +36,12 @@ namespace gui ...@@ -21,6 +36,12 @@ namespace gui
IGUIContextMenu(IGUIEnvironment* environment, IGUIElement* parent, s32 id, core::rect<s32> rectangle) IGUIContextMenu(IGUIEnvironment* environment, IGUIElement* parent, s32 id, core::rect<s32> rectangle)
: IGUIElement(EGUIET_CONTEXT_MENU, environment, parent, id, rectangle) {} : IGUIElement(EGUIET_CONTEXT_MENU, environment, parent, id, rectangle) {}
//! set behaviour when menus are closed
virtual void setCloseHandling(ECONTEXT_MENU_CLOSE onClose) = 0;
//! get current behaviour when the menue will be closed
virtual ECONTEXT_MENU_CLOSE getCloseHandling() const = 0;
//! Get amount of menu items //! Get amount of menu items
virtual u32 getItemCount() const = 0; virtual u32 getItemCount() const = 0;
...@@ -36,7 +57,30 @@ namespace gui ...@@ -36,7 +57,30 @@ namespace gui
\param checked: Specifies if the menu item should be initially checked. \param checked: Specifies if the menu item should be initially checked.
\return Returns the index of the new item */ \return Returns the index of the new item */
virtual u32 addItem(const wchar_t* text, s32 commandId=-1, bool enabled=true, virtual u32 addItem(const wchar_t* text, s32 commandId=-1, bool enabled=true,
bool hasSubMenu=false, bool checked=false) = 0; bool hasSubMenu=false, bool checked=false, bool autoChecking=false) = 0;
//! Insert a menu item at specified position.
/** \param idx: Position to insert the new element,
should be smaller than itemcount otherwise the item is added to the end.
\param text: Text of menu item. Set this to 0 to create
an separator instead of a real item, which is the same like
calling addSeparator();
\param commandId: Command id of menu item, a simple id you may
set to whatever you want.
\param enabled: Specifies if the menu item should be enabled.
\param hasSubMenu: Set this to true if there should be a submenu
at this item. You can acess this submenu via getSubMenu().
\param checked: Specifies if the menu item should be initially checked.
\return Returns the index of the new item */
virtual u32 insertItem(u32 idx, const wchar_t* text, s32 commandId=-1, bool enabled=true,
bool hasSubMenu=false, bool checked=false, bool autoChecking=false) = 0;
//! Find an item by it's CommandID
/**
\param commandId: We are looking for the first item which has this commandID
\param idxStartSearch: Start searching from this index.
\return Returns the index of the item when found or otherwise -1. */
virtual s32 findItemWithCommandId(s32 commandId, u32 idxStartSearch=0) const = 0;
//! Adds a separator item to the menu //! Adds a separator item to the menu
virtual void addSeparator() = 0; virtual void addSeparator() = 0;
...@@ -94,6 +138,15 @@ namespace gui ...@@ -94,6 +138,15 @@ namespace gui
\param idx: Zero based index of the menu item \param idx: Zero based index of the menu item
\return Returns a pointer to the submenu of an item. */ \return Returns a pointer to the submenu of an item. */
virtual IGUIContextMenu* getSubMenu(u32 idx) const = 0; virtual IGUIContextMenu* getSubMenu(u32 idx) const = 0;
//! should the element change the checked status on clicking
virtual void setItemAutoChecking(u32 idx, bool autoChecking) = 0;
//! does the element change the checked status on clicking
virtual bool getItemAutoChecking(u32 idx) const = 0;
//! When an eventparent is set it receives events instead of the usual parent element
virtual void setEventParent(IGUIElement *parent) = 0;
}; };
} // end namespace gui } // end namespace gui
......
...@@ -24,7 +24,7 @@ CGUIContextMenu::CGUIContextMenu(IGUIEnvironment* environment, ...@@ -24,7 +24,7 @@ CGUIContextMenu::CGUIContextMenu(IGUIEnvironment* environment,
IGUIElement* parent, s32 id, IGUIElement* parent, s32 id,
core::rect<s32> rectangle, bool getFocus, bool allowFocus) core::rect<s32> rectangle, bool getFocus, bool allowFocus)
: IGUIContextMenu(environment, parent, id, rectangle), EventParent(0), LastFont(0), : IGUIContextMenu(environment, parent, id, rectangle), EventParent(0), LastFont(0),
HighLighted(-1), ChangeTime(0), AllowFocus(allowFocus) CloseHandling(ECMC_REMOVE), HighLighted(-1), ChangeTime(0), AllowFocus(allowFocus)
{ {
#ifdef _DEBUG #ifdef _DEBUG
setDebugName("CGUIContextMenu"); setDebugName("CGUIContextMenu");
...@@ -51,6 +51,17 @@ CGUIContextMenu::~CGUIContextMenu() ...@@ -51,6 +51,17 @@ CGUIContextMenu::~CGUIContextMenu()
LastFont->drop(); LastFont->drop();
} }
//! set behaviour when menus are closed
void CGUIContextMenu::setCloseHandling(ECONTEXT_MENU_CLOSE onClose)
{
CloseHandling = onClose;
}
//! get current behaviour when the menue will be closed
ECONTEXT_MENU_CLOSE CGUIContextMenu::getCloseHandling() const
{
return CloseHandling;
}
//! Returns amount of menu items //! Returns amount of menu items
u32 CGUIContextMenu::getItemCount() const u32 CGUIContextMenu::getItemCount() const
...@@ -60,29 +71,57 @@ u32 CGUIContextMenu::getItemCount() const ...@@ -60,29 +71,57 @@ u32 CGUIContextMenu::getItemCount() const
//! Adds a menu item. //! Adds a menu item.
u32 CGUIContextMenu::addItem(const wchar_t* text, s32 id, bool enabled, bool hasSubMenu, bool checked) 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; SItem s;
s.Enabled = enabled; s.Enabled = enabled;
s.Checked = checked; s.Checked = checked;
s.AutoChecking = autoChecking;
s.Text = text; s.Text = text;
s.IsSeparator = (text == 0); s.IsSeparator = (text == 0);
s.SubMenu = 0; s.SubMenu = 0;
s.CommandId = id; s.CommandId = commandId;
if (hasSubMenu) if (hasSubMenu)
{ {
s.SubMenu = new CGUIContextMenu(Environment, this, id, s.SubMenu = new CGUIContextMenu(Environment, this, commandId,
core::rect<s32>(0,0,100,100), false, false); core::rect<s32>(0,0,100,100), false, false);
s.SubMenu->setVisible(false); s.SubMenu->setVisible(false);
} }
u32 result = idx;
if ( idx < Items.size() )
{
Items.insert(s, idx);
}
else
{
Items.push_back(s); Items.push_back(s);
result = Items.size() - 1;
}
recalculateSize(); recalculateSize();
return Items.size() - 1; return result;
} }
s32 CGUIContextMenu::findItemWithCommandId(s32 commandId, u32 idxStartSearch) const
{
for ( u32 i=idxStartSearch; i<Items.size(); ++i )
{
if ( Items[i].CommandId == commandId )
{
return (s32)i;
}
}
return -1;
}
//! Adds a sub menu from an element that already exists. //! Adds a sub menu from an element that already exists.
void CGUIContextMenu::setSubMenu(u32 index, CGUIContextMenu* menu) void CGUIContextMenu::setSubMenu(u32 index, CGUIContextMenu* menu)
...@@ -114,7 +153,7 @@ void CGUIContextMenu::setSubMenu(u32 index, CGUIContextMenu* menu) ...@@ -114,7 +153,7 @@ void CGUIContextMenu::setSubMenu(u32 index, CGUIContextMenu* menu)
//! Adds a separator item to the menu //! Adds a separator item to the menu
void CGUIContextMenu::addSeparator() void CGUIContextMenu::addSeparator()
{ {
addItem(0, -1, true, false, false); addItem(0, -1, true, false, false, false);
} }
...@@ -138,6 +177,24 @@ void CGUIContextMenu::setItemText(u32 idx, const wchar_t* text) ...@@ -138,6 +177,24 @@ void CGUIContextMenu::setItemText(u32 idx, const wchar_t* text)
recalculateSize(); 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 //! Returns if a menu item is enabled
bool CGUIContextMenu::isItemEnabled(u32 idx) const bool CGUIContextMenu::isItemEnabled(u32 idx) const
...@@ -231,8 +288,17 @@ bool CGUIContextMenu::OnEvent(const SEvent& event) ...@@ -231,8 +288,17 @@ bool CGUIContextMenu::OnEvent(const SEvent& event)
if (event.GUIEvent.Caller == this && !isMyChild(event.GUIEvent.Element) && AllowFocus) if (event.GUIEvent.Caller == this && !isMyChild(event.GUIEvent.Element) && AllowFocus)
{ {
// set event parent of submenus // set event parent of submenus
setEventParent(Parent); setEventParent(EventParent ? EventParent : Parent);
if ( CloseHandling & ECMC_HIDE )
{
setVisible(false);
}
if ( CloseHandling & ECMC_REMOVE )
{
remove(); remove();
}
return false; return false;
} }
break; break;
...@@ -326,16 +392,20 @@ u32 CGUIContextMenu::sendClick(const core::position2d<s32>& p) ...@@ -326,16 +392,20 @@ u32 CGUIContextMenu::sendClick(const core::position2d<s32>& p)
Items[HighLighted].SubMenu) Items[HighLighted].SubMenu)
return 2; return 2;
if ( Items[HighLighted].AutoChecking )
{
Items[HighLighted].Checked = Items[HighLighted].Checked ? false : true;
}
SEvent event; SEvent event;
event.EventType = EET_GUI_EVENT; event.EventType = EET_GUI_EVENT;
event.GUIEvent.Caller = this; event.GUIEvent.Caller = this;
event.GUIEvent.Element = 0; event.GUIEvent.Element = 0;
event.GUIEvent.EventType = EGET_MENU_ITEM_SELECTED; event.GUIEvent.EventType = EGET_MENU_ITEM_SELECTED;
if (Parent)
Parent->OnEvent(event);
else
if (EventParent) if (EventParent)
EventParent->OnEvent(event); EventParent->OnEvent(event);
else if (Parent)
Parent->OnEvent(event);
return 1; return 1;
} }
...@@ -644,6 +714,8 @@ void CGUIContextMenu::serializeAttributes(io::IAttributes* out, io::SAttributeRe ...@@ -644,6 +714,8 @@ void CGUIContextMenu::serializeAttributes(io::IAttributes* out, io::SAttributeRe
out->addInt("ParentItem", i); out->addInt("ParentItem", i);
} }
out->addInt("CloseHandling", (s32)CloseHandling);
// write out the item list // write out the item list
out->addInt("ItemCount", Items.size()); out->addInt("ItemCount", Items.size());
...@@ -662,6 +734,10 @@ void CGUIContextMenu::serializeAttributes(io::IAttributes* out, io::SAttributeRe ...@@ -662,6 +734,10 @@ void CGUIContextMenu::serializeAttributes(io::IAttributes* out, io::SAttributeRe
out->addInt(tmp.c_str(), Items[i].CommandId); out->addInt(tmp.c_str(), Items[i].CommandId);
tmp = "Enabled"; tmp += i; tmp = "Enabled"; tmp += i;
out->addBool(tmp.c_str(), Items[i].Enabled); 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);
} }
} }
} }
...@@ -678,6 +754,7 @@ void CGUIContextMenu::deserializeAttributes(io::IAttributes* in, io::SAttributeR ...@@ -678,6 +754,7 @@ void CGUIContextMenu::deserializeAttributes(io::IAttributes* in, io::SAttributeR
if (Parent && ( Parent->getType() == EGUIET_CONTEXT_MENU || Parent->getType() == EGUIET_MENU ) ) if (Parent && ( Parent->getType() == EGUIET_CONTEXT_MENU || Parent->getType() == EGUIET_MENU ) )
((CGUIContextMenu*)Parent)->setSubMenu(in->getAttributeAsInt("ParentItem"),this); ((CGUIContextMenu*)Parent)->setSubMenu(in->getAttributeAsInt("ParentItem"),this);
CloseHandling = (ECONTEXT_MENU_CLOSE)in->getAttributeAsInt("CloseHandling");
removeAllItems(); removeAllItems();
...@@ -688,28 +765,37 @@ void CGUIContextMenu::deserializeAttributes(io::IAttributes* in, io::SAttributeR ...@@ -688,28 +765,37 @@ void CGUIContextMenu::deserializeAttributes(io::IAttributes* in, io::SAttributeR
{ {
core::stringc tmp; core::stringc tmp;
core::stringw txt; core::stringw txt;
s32 commandid; s32 commandid=-1;
bool enabled; bool enabled=true;
bool checked; bool checked=false;
bool autochecking=false;
tmp = "IsSeparator"; tmp += i; tmp = "IsSeparator"; tmp += i;
if ( in->getAttributeAsBool(tmp.c_str()) ) if ( in->existsAttribute(tmp.c_str()) && in->getAttributeAsBool(tmp.c_str()) )
addSeparator(); addSeparator();
else else
{ {
tmp = "Text"; tmp += i; tmp = "Text"; tmp += i;
if ( in->existsAttribute(tmp.c_str()) )
txt = in->getAttributeAsStringW(tmp.c_str()); txt = in->getAttributeAsStringW(tmp.c_str());
tmp = "CommandID"; tmp += i; tmp = "CommandID"; tmp += i;
if ( in->existsAttribute(tmp.c_str()) )
commandid = in->getAttributeAsInt(tmp.c_str()); commandid = in->getAttributeAsInt(tmp.c_str());
tmp = "Enabled"; tmp += i; tmp = "Enabled"; tmp += i;
if ( in->existsAttribute(tmp.c_str()) )
enabled = in->getAttributeAsBool(tmp.c_str()); enabled = in->getAttributeAsBool(tmp.c_str());
tmp = "Checked"; tmp += i; tmp = "Checked"; tmp += i;
if ( in->existsAttribute(tmp.c_str()) )
checked = in->getAttributeAsBool(tmp.c_str()); checked = in->getAttributeAsBool(tmp.c_str());
addItem(core::stringw(txt.c_str()).c_str(), commandid, enabled, false, checked); 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);
} }
} }
......
...@@ -31,12 +31,25 @@ namespace gui ...@@ -31,12 +31,25 @@ namespace gui
//! destructor //! destructor
virtual ~CGUIContextMenu(); virtual ~CGUIContextMenu();
//! set behaviour when menus are closed
virtual void setCloseHandling(ECONTEXT_MENU_CLOSE onClose);
//! get current behaviour when the menue will be closed
virtual ECONTEXT_MENU_CLOSE getCloseHandling() const;
//! Returns amount of menu items //! Returns amount of menu items
virtual u32 getItemCount() const; virtual u32 getItemCount() const;
//! Adds a menu item. //! Adds a menu item.
virtual u32 addItem(const wchar_t* text, s32 commandid, virtual u32 addItem(const wchar_t* text, s32 commandid,
bool enabled, bool hasSubMenu, bool checked); bool enabled, bool hasSubMenu, bool checked, bool autoChecking);
//! Insert a menu item at specified position.
virtual u32 insertItem(u32 idx, const wchar_t* text, s32 commandId, bool enabled,
bool hasSubMenu, bool checked, bool autoChecking);
//! Find a item which has the given CommandId starting from given index
virtual s32 findItemWithCommandId(s32 commandId, u32 idxStartSearch) const;
//! Adds a separator item to the menu //! Adds a separator item to the menu
virtual void addSeparator(); virtual void addSeparator();
...@@ -81,6 +94,12 @@ namespace gui ...@@ -81,6 +94,12 @@ namespace gui
//! Sets the visible state of this element. //! Sets the visible state of this element.
virtual void setVisible(bool visible); virtual void setVisible(bool visible);
//! should the element change the checked status on clicking
virtual void setItemAutoChecking(u32 idx, bool autoChecking);
//! does the element change the checked status on clicking
virtual bool getItemAutoChecking(u32 idx) const;
//! Returns command id of a menu item //! Returns command id of a menu item
virtual s32 getItemCommandId(u32 idx) const; virtual s32 getItemCommandId(u32 idx) const;
...@@ -90,6 +109,9 @@ namespace gui ...@@ -90,6 +109,9 @@ namespace gui
//! Adds a sub menu from an element that already exists. //! Adds a sub menu from an element that already exists.
virtual void setSubMenu(u32 index, CGUIContextMenu* menu); virtual void setSubMenu(u32 index, CGUIContextMenu* menu);
//! When an eventparent is set it receives events instead of the usual parent element
virtual void setEventParent(IGUIElement *parent);
//! Writes attributes of the element. //! Writes attributes of the element.
virtual void serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options) const; virtual void serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options) const;
...@@ -107,6 +129,7 @@ namespace gui ...@@ -107,6 +129,7 @@ namespace gui
bool IsSeparator; bool IsSeparator;
bool Enabled; bool Enabled;
bool Checked; bool Checked;
bool AutoChecking;
core::dimension2d<u32> Dim; core::dimension2d<u32> Dim;
s32 PosY; s32 PosY;
CGUIContextMenu* SubMenu; CGUIContextMenu* SubMenu;
...@@ -130,12 +153,12 @@ namespace gui ...@@ -130,12 +153,12 @@ namespace gui
//! Gets drawing rect of Item //! Gets drawing rect of Item
virtual core::rect<s32> getRect(const SItem& i, const core::rect<s32>& absolute) const; virtual core::rect<s32> getRect(const SItem& i, const core::rect<s32>& absolute) const;
void setEventParent(IGUIElement *parent);
core::array<SItem> Items; core::array<SItem> Items;
core::position2d<s32> Pos; core::position2d<s32> Pos;
IGUIElement* EventParent; IGUIElement* EventParent;
IGUIFont *LastFont; IGUIFont *LastFont;
ECONTEXT_MENU_CLOSE CloseHandling;
s32 HighLighted; s32 HighLighted;
u32 ChangeTime; u32 ChangeTime;
bool AllowFocus; bool AllowFocus;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment