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
{
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.
class IGUIContextMenu : public IGUIElement
......@@ -21,6 +36,12 @@ namespace gui
IGUIContextMenu(IGUIEnvironment* environment, IGUIElement* parent, s32 id, core::rect<s32> 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
virtual u32 getItemCount() const = 0;
......@@ -36,7 +57,30 @@ namespace gui
\param checked: Specifies if the menu item should be initially checked.
\return Returns the index of the new item */
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
virtual void addSeparator() = 0;
......@@ -94,6 +138,15 @@ namespace gui
\param idx: Zero based index of the menu item
\return Returns a pointer to the submenu of an item. */
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
......
......@@ -24,7 +24,7 @@ CGUIContextMenu::CGUIContextMenu(IGUIEnvironment* environment,
IGUIElement* parent, s32 id,
core::rect<s32> rectangle, bool getFocus, bool allowFocus)
: 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
setDebugName("CGUIContextMenu");
......@@ -51,6 +51,17 @@ CGUIContextMenu::~CGUIContextMenu()
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
u32 CGUIContextMenu::getItemCount() const
......@@ -60,29 +71,57 @@ u32 CGUIContextMenu::getItemCount() const
//! 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;
s.Enabled = enabled;
s.Checked = checked;
s.AutoChecking = autoChecking;
s.Text = text;
s.IsSeparator = (text == 0);
s.SubMenu = 0;
s.CommandId = id;
s.CommandId = commandId;
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);
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 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.
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
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)
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
......@@ -231,8 +288,17 @@ bool CGUIContextMenu::OnEvent(const SEvent& event)
if (event.GUIEvent.Caller == this && !isMyChild(event.GUIEvent.Element) && AllowFocus)
{
// set event parent of submenus
setEventParent(Parent);
setEventParent(EventParent ? EventParent : Parent);
if ( CloseHandling & ECMC_HIDE )
{
setVisible(false);
}
if ( CloseHandling & ECMC_REMOVE )
{
remove();
}
return false;
}
break;
......@@ -326,16 +392,20 @@ u32 CGUIContextMenu::sendClick(const core::position2d<s32>& p)
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 (Parent)
Parent->OnEvent(event);
else
if (EventParent)
EventParent->OnEvent(event);
else if (Parent)
Parent->OnEvent(event);
return 1;
}
......@@ -644,6 +714,8 @@ void CGUIContextMenu::serializeAttributes(io::IAttributes* out, io::SAttributeRe
out->addInt("ParentItem", i);
}
out->addInt("CloseHandling", (s32)CloseHandling);
// write out the item list
out->addInt("ItemCount", Items.size());
......@@ -662,6 +734,10 @@ void CGUIContextMenu::serializeAttributes(io::IAttributes* out, io::SAttributeRe
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);
}
}
}
......@@ -678,6 +754,7 @@ void CGUIContextMenu::deserializeAttributes(io::IAttributes* in, io::SAttributeR
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();
......@@ -688,28 +765,37 @@ void CGUIContextMenu::deserializeAttributes(io::IAttributes* in, io::SAttributeR
{
core::stringc tmp;
core::stringw txt;
s32 commandid;
bool enabled;
bool checked;
s32 commandid=-1;
bool enabled=true;
bool checked=false;
bool autochecking=false;
tmp = "IsSeparator"; tmp += i;
if ( in->getAttributeAsBool(tmp.c_str()) )
if ( in->existsAttribute(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());
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
//! destructor
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
virtual u32 getItemCount() const;
//! Adds a menu item.
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
virtual void addSeparator();
......@@ -81,6 +94,12 @@ namespace gui
//! Sets the visible state of this element.
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
virtual s32 getItemCommandId(u32 idx) const;
......@@ -90,6 +109,9 @@ namespace gui
//! Adds a sub menu from an element that already exists.
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.
virtual void serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options) const;
......@@ -107,6 +129,7 @@ namespace gui
bool IsSeparator;
bool Enabled;
bool Checked;
bool AutoChecking;
core::dimension2d<u32> Dim;
s32 PosY;
CGUIContextMenu* SubMenu;
......@@ -130,12 +153,12 @@ namespace gui
//! Gets drawing rect of Item
virtual core::rect<s32> getRect(const SItem& i, const core::rect<s32>& absolute) const;
void setEventParent(IGUIElement *parent);
core::array<SItem> Items;
core::position2d<s32> Pos;
IGUIElement* EventParent;
IGUIFont *LastFont;
ECONTEXT_MENU_CLOSE CloseHandling;
s32 HighLighted;
u32 ChangeTime;
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