mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-01 17:35:34 -04:00
add has_method to work around firefox bug
This commit is contained in:
parent
9f56a959c2
commit
ce23653ac2
@ -70,6 +70,11 @@ object_set_property(P3D_object *object, const char *property,
|
||||
return ((P3DObject *)object)->set_property(property, value);
|
||||
}
|
||||
|
||||
static bool
|
||||
object_has_method(const P3D_object *object, const char *method_name) {
|
||||
return ((const P3DObject *)object)->has_method(method_name);
|
||||
}
|
||||
|
||||
static P3D_object *
|
||||
object_call(const P3D_object *object, const char *method_name,
|
||||
P3D_object *params[], int num_params) {
|
||||
@ -95,6 +100,7 @@ P3D_class_definition P3DObject::_object_class = {
|
||||
&object_get_repr,
|
||||
&object_get_property,
|
||||
&object_set_property,
|
||||
&object_has_method,
|
||||
&object_call,
|
||||
&object_eval,
|
||||
};
|
||||
@ -163,6 +169,11 @@ generic_set_property(P3D_object *object, const char *property,
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool
|
||||
generic_has_method(const P3D_object *object, const char *method_name) {
|
||||
return ((const P3DObject *)object)->has_method(method_name);
|
||||
}
|
||||
|
||||
static P3D_object *
|
||||
generic_call(const P3D_object *object, const char *method_name,
|
||||
P3D_object *params[], int num_params) {
|
||||
@ -188,6 +199,7 @@ P3D_class_definition P3DObject::_generic_class = {
|
||||
&generic_get_repr,
|
||||
&generic_get_property,
|
||||
&generic_set_property,
|
||||
&generic_has_method,
|
||||
&generic_call,
|
||||
&generic_eval,
|
||||
};
|
||||
@ -297,6 +309,17 @@ set_property(const string &property, P3D_object *value) {
|
||||
return false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: P3DObject::has_method
|
||||
// Access: Public, Virtual
|
||||
// Description: Returns true if the named method exists on this
|
||||
// object, false otherwise.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool P3DObject::
|
||||
has_method(const string &method_name) const {
|
||||
return false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: P3DObject::call
|
||||
// Access: Public, Virtual
|
||||
|
@ -46,6 +46,7 @@ public:
|
||||
virtual P3D_object *get_property(const string &property) const;
|
||||
virtual bool set_property(const string &property, P3D_object *value);
|
||||
|
||||
virtual bool has_method(const string &method_name) const;
|
||||
virtual P3D_object *call(const string &method_name,
|
||||
P3D_object *params[], int num_params) const;
|
||||
virtual P3D_object *eval(const string &expression) const;
|
||||
|
@ -173,6 +173,29 @@ set_property(const string &property, P3D_object *value) {
|
||||
return bresult;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: P3DPythonObject::has_method
|
||||
// Access: Public, Virtual
|
||||
// Description: Returns true if the named method exists on this
|
||||
// object, false otherwise.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool P3DPythonObject::
|
||||
has_method(const string &method_name) const {
|
||||
bool bresult = false;
|
||||
|
||||
P3D_object *params[1];
|
||||
params[0] = new P3DStringObject(method_name);
|
||||
|
||||
P3D_object *result = call("__has_method__", params, 1);
|
||||
|
||||
if (result != NULL) {
|
||||
bresult = P3D_OBJECT_GET_BOOL(result);
|
||||
P3D_OBJECT_FINISH(result);
|
||||
}
|
||||
|
||||
return bresult;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: P3DPythonObject::call
|
||||
// Access: Public, Virtual
|
||||
|
@ -44,6 +44,7 @@ public:
|
||||
virtual P3D_object *get_property(const string &property) const;
|
||||
virtual bool set_property(const string &property, P3D_object *value);
|
||||
|
||||
virtual bool has_method(const string &method_name) const;
|
||||
virtual P3D_object *call(const string &method_name,
|
||||
P3D_object *params[], int num_params) const;
|
||||
|
||||
|
@ -395,6 +395,28 @@ handle_pyobj_command(TiXmlElement *xcommand, bool needs_response,
|
||||
}
|
||||
}
|
||||
|
||||
} else if (strcmp(method_name, "__has_method__") == 0) {
|
||||
char *property_name;
|
||||
result = Py_False;
|
||||
if (PyArg_ParseTuple(params, "s", &property_name)) {
|
||||
if (*property_name) {
|
||||
// Check for a callable method
|
||||
if (PyObject_HasAttrString(obj, property_name)) {
|
||||
PyObject *prop = PyObject_GetAttrString(obj, property_name);
|
||||
if (PyCallable_Check(prop)) {
|
||||
result = Py_True;
|
||||
}
|
||||
Py_DECREF(prop);
|
||||
}
|
||||
} else {
|
||||
// Check for the default method
|
||||
if (PyCallable_Check(obj)) {
|
||||
result = Py_True;
|
||||
}
|
||||
}
|
||||
}
|
||||
Py_INCREF(result);
|
||||
|
||||
} else {
|
||||
// Not a special-case name. Call the named method.
|
||||
PyObject *method = PyObject_GetAttrString(obj, (char *)method_name);
|
||||
|
@ -377,6 +377,14 @@ typedef bool
|
||||
P3D_object_set_property_method(P3D_object *object, const char *property,
|
||||
P3D_object *value);
|
||||
|
||||
/* Returns true if the indicated method name exists on the object,
|
||||
false otherwise. In the Python case, this actually returns true if
|
||||
the object has the indicated property, and that property represents
|
||||
a callable object. If method_name is empty or NULL, returns true
|
||||
if the object itself is callable. */
|
||||
typedef bool
|
||||
P3D_object_has_method_method(const P3D_object *object, const char *method_name);
|
||||
|
||||
/* Invokes a named method on the object. If method_name is empty or
|
||||
NULL, invokes the object itself as a function. You must pass an
|
||||
array of P3D_objects as the list of parameters. The ownership of
|
||||
@ -416,6 +424,7 @@ typedef struct _P3D_class_definition {
|
||||
P3D_object_get_property_method *_get_property;
|
||||
P3D_object_set_property_method *_set_property;
|
||||
|
||||
P3D_object_has_method_method *_has_method;
|
||||
P3D_object_call_method *_call;
|
||||
P3D_object_eval_method *_eval;
|
||||
|
||||
@ -444,6 +453,7 @@ struct _P3D_object {
|
||||
#define P3D_OBJECT_GET_PROPERTY(object, property) ((object)->_class->_get_property((object), (property)))
|
||||
#define P3D_OBJECT_SET_PROPERTY(object, property, value) ((object)->_class->_set_property((object), (property), (value)))
|
||||
|
||||
#define P3D_OBJECT_HAS_METHOD(object, property) ((object)->_class->_has_method((object), (property)))
|
||||
#define P3D_OBJECT_CALL(object, method_name, params, num_params) ((object)->_class->_call((object), (method_name), (params), (num_params)))
|
||||
#define P3D_OBJECT_EVAL(object, expression) ((object)->_class->_eval((object), (expression)))
|
||||
|
||||
|
@ -101,11 +101,26 @@ invalidate() {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool PPPandaObject::
|
||||
has_method(NPIdentifier name) {
|
||||
string property_name = identifier_to_string(name);
|
||||
logfile << "has_method: " << this << ", " << property_name << "\n" << flush;
|
||||
string method_name = identifier_to_string(name);
|
||||
logfile << "has_method: " << this << ", " << method_name << "\n" << flush;
|
||||
if (_p3d_object == NULL) {
|
||||
// Not powered up yet.
|
||||
return false;
|
||||
}
|
||||
|
||||
// As below, we always return true. Why not?
|
||||
return true;
|
||||
// Unlike has_property(), below, it turns out that we really do need
|
||||
// to honestly answer whether there is a method by this name,
|
||||
// because if there is, then Firefox won't query the property in a
|
||||
// meaningful fashion.
|
||||
|
||||
// Of course, in Python the distinction between property and method
|
||||
// is a little looser than Firefox seems to want to make it, and
|
||||
// sometimes you have an object which is both. This could become
|
||||
// problematic in obscure situations. Too bad, say I. Mozilla's
|
||||
// bug, not mine.
|
||||
|
||||
bool result = P3D_OBJECT_HAS_METHOD(_p3d_object, method_name.c_str());
|
||||
return result;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
Loading…
x
Reference in New Issue
Block a user