Support deleting GUI Object event handlers following af9c336b43, refs #5387.

Differential Revision: https://code.wildfiregames.com/D2395
Reported by: nani
Tested on: gcc 9.2.0, Jenkins/vs2015

This was SVN commit r23103.
This commit is contained in:
elexis 2019-10-28 11:35:04 +00:00
parent 8061bd360f
commit f7161ad5c6
7 changed files with 66 additions and 8 deletions

View File

@ -19,7 +19,6 @@ class MainMenuItemHandler
this.setupMenuButtons(this.mainMenuButtons.children, this.menuItems);
this.setupHotkeys(this.menuItems);
this.mainMenu.onTick = this.onTick.bind(this);
Engine.GetGUIObjectByName("closeMenuButton").onPress = this.closeSubmenu.bind(this);
}
@ -93,6 +92,10 @@ class MainMenuItemHandler
size.top = this.submenu.size.bottom;
this.MainMenuPanelRightBorderBottom.size = size;
}
// Start animation
this.lastTickTime = Date.now();
this.mainMenu.onTick = this.onTick.bind(this);
}
closeSubmenu()
@ -110,14 +113,19 @@ class MainMenuItemHandler
onTick()
{
let now = Date.now();
if (now == this.lastTickTime)
return;
let maxOffset = this.mainMenu.size.right - this.submenu.size.left;
let offset = Math.min(this.MenuSpeed * (now - this.lastTickTime), maxOffset);
this.lastTickTime = now;
if (this.submenu.hidden || offset <= 0)
if (this.submenu.hidden || !offset)
{
delete this.mainMenu.onTick;
return;
}
let size = this.submenu.size;
size.left += offset;

View File

@ -23,8 +23,7 @@ class SplashScreenHandler
if (this.showSplashScreen)
this.openPage();
// TODO: support actually deleting the handler
this.mainMenuPage.onTick = () => {};
delete this.mainMenuPage.onTick;
}
openPage()

View File

@ -101,8 +101,7 @@ class Menu
if (maxOffset <= 0)
{
// TODO: support actually deleting the handler
this.menuButtonPanel.onTick = () => {};
delete this.menuButtonPanel.onTick;
return;
}

View File

@ -334,6 +334,19 @@ void IGUIObject::SetScriptHandler(const CStr& Action, JS::HandleObject Function)
m_ScriptHandlers[Action] = JS::Heap<JSObject*>(Function);
}
void IGUIObject::UnsetScriptHandler(const CStr& Action)
{
std::map<CStr, JS::Heap<JSObject*> >::iterator it = m_ScriptHandlers.find(Action);
if (it == m_ScriptHandlers.end())
return;
m_ScriptHandlers.erase(it);
if (m_ScriptHandlers.empty())
JS_RemoveExtraGCRootsTracer(m_pGUI.GetScriptInterface()->GetJSRuntime(), Trace, this);
}
InReaction IGUIObject::SendEvent(EGUIMessageType type, const CStr& EventName)
{
PROFILE2_EVENT("gui event");

View File

@ -57,6 +57,7 @@ class IGUIObject
// Allow getProperty to access things like GetParent()
friend bool JSI_IGUIObject::getProperty(JSContext* cx, JS::HandleObject obj, JS::HandleId id, JS::MutableHandleValue vp);
friend bool JSI_IGUIObject::setProperty(JSContext* cx, JS::HandleObject obj, JS::HandleId id, JS::MutableHandleValue vp, JS::ObjectOpResult& result);
friend bool JSI_IGUIObject::deleteProperty(JSContext* cx, JS::HandleObject obj, JS::HandleId id, JS::ObjectOpResult& result);
friend bool JSI_IGUIObject::getComputedSize(JSContext* cx, uint argc, JS::Value* vp);
public:
@ -385,8 +386,16 @@ protected:
*/
void ScriptEvent(const CStr& Action, const JS::HandleValueArray& paramData);
/**
* Assigns a JS function to the event name.
*/
void SetScriptHandler(const CStr& Action, JS::HandleObject Function);
/**
* Deletes an event handler assigned to the given name, if such a handler exists.
*/
void UnsetScriptHandler(const CStr& Action);
/**
* Inputes the object that is currently hovered, this function
* updates this object accordingly (i.e. if it's the object

View File

@ -27,8 +27,10 @@
JSClass JSI_IGUIObject::JSI_class = {
"GUIObject", JSCLASS_HAS_PRIVATE,
nullptr, nullptr,
JSI_IGUIObject::getProperty, JSI_IGUIObject::setProperty,
nullptr,
JSI_IGUIObject::deleteProperty,
JSI_IGUIObject::getProperty,
JSI_IGUIObject::setProperty,
nullptr, nullptr, nullptr, nullptr,
nullptr, nullptr, nullptr, nullptr
};
@ -174,6 +176,33 @@ bool JSI_IGUIObject::setProperty(JSContext* cx, JS::HandleObject obj, JS::Handle
return result.fail(JSMSG_UNDEFINED_PROP);
}
bool JSI_IGUIObject::deleteProperty(JSContext* cx, JS::HandleObject obj, JS::HandleId id, JS::ObjectOpResult& result)
{
IGUIObject* e = ScriptInterface::GetPrivate<IGUIObject>(cx, obj, &JSI_IGUIObject::JSI_class);
if (!e)
return result.fail(JSMSG_NOT_NONNULL_OBJECT);
JSAutoRequest rq(cx);
JS::RootedValue idval(cx);
if (!JS_IdToValue(cx, id, &idval))
return result.fail(JSMSG_NOT_NONNULL_OBJECT);
std::string propName;
if (!ScriptInterface::FromJSVal(cx, idval, propName))
return result.fail(JSMSG_UNDEFINED_PROP);
// event handlers
if (propName.substr(0, 2) == "on")
{
CStr eventName(CStr(propName.substr(2)).LowerCase());
e->UnsetScriptHandler(eventName);
return result.succeed();
}
JS_ReportError(cx, "Only event handlers can be deleted from GUI objects!");
return result.fail(JSMSG_UNDEFINED_PROP);
}
bool JSI_IGUIObject::toString(JSContext* cx, uint argc, JS::Value* vp)
{
// No JSAutoRequest needed for these calls

View File

@ -29,6 +29,7 @@ namespace JSI_IGUIObject
bool getProperty(JSContext* cx, JS::HandleObject obj, JS::HandleId id, JS::MutableHandleValue vp);
bool setProperty(JSContext* cx, JS::HandleObject obj, JS::HandleId id, JS::MutableHandleValue vp, JS::ObjectOpResult& result);
bool deleteProperty(JSContext* cx, JS::HandleObject obj, JS::HandleId id, JS::ObjectOpResult& result);
bool toString(JSContext* cx, uint argc, JS::Value* vp);
bool focus(JSContext* cx, uint argc, JS::Value* vp);
bool blur(JSContext* cx, uint argc, JS::Value* vp);