00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #ifndef OBJECT_BINDING_H
00025 #define OBJECT_BINDING_H
00026
00027 #include <kdemacros.h>
00028
00029 #include "static_binding.h"
00030 #include "variant_binding.h"
00031 #include "pointer.h"
00032 #include "kjseglobal.h"
00033
00040 #define START_OBJECT_METHOD( METHODNAME, TYPE) \
00041 KJS::JSValue *METHODNAME( KJS::ExecState *exec, KJS::JSObject *self, const KJS::List &args ) \
00042 { \
00043 Q_UNUSED(exec);\
00044 Q_UNUSED(self);\
00045 Q_UNUSED(args);\
00046 KJS::JSValue *result = KJS::jsNull(); \
00047 KJSEmbed::ObjectBinding *imp = KJSEmbed::extractBindingImp<KJSEmbed::ObjectBinding>(exec, self ); \
00048 if( imp ) \
00049 { \
00050 TYPE *object = imp->object<TYPE>(); \
00051 if( object ) \
00052 {
00053
00057 #define END_OBJECT_METHOD \
00058 } \
00059 else \
00060 KJS::throwError(exec, KJS::ReferenceError, QString("O: The internal object died."));\
00061 } \
00062 else \
00063 KJS::throwError(exec, KJS::GeneralError, QString("Object cast failed."));\
00064 return result; \
00065 }
00066
00067 #define START_STATIC_OBJECT_METHOD( METHODNAME ) \
00068 KJS::JSValue *METHODNAME( KJS::ExecState *exec, KJS::JSObject *self, const KJS::List &args ) \
00069 {\
00070 Q_UNUSED(exec);\
00071 Q_UNUSED(self);\
00072 Q_UNUSED(args);\
00073 KJS::JSValue *result = KJS::jsNull(); \
00074
00075 #define END_STATIC_OBJECT_METHOD \
00076 return result; \
00077 }
00078
00079 namespace KJSEmbed
00080 {
00081 class KJSEMBED_EXPORT ObjectFactory
00082 {
00083 public:
00084 static const Method ObjectMethods[];
00085 static const Method *methods(){ return ObjectMethods;}
00086 };
00087
00088 class KJSEMBED_EXPORT ObjectBinding : public ProxyBinding
00089 {
00090 public:
00091 enum Ownership { CPPOwned, QObjOwned, JSOwned };
00092 static const KJS::ClassInfo info;
00093
00094 private:
00095 const char *m_name;
00096 mutable PointerBase *m_value;
00097 Ownership m_owner;
00098
00099 public:
00100 template <typename T>
00101 ObjectBinding( KJS::ExecState *exec, const char *typeName, T *ptr )
00102 : ProxyBinding(exec),
00103 m_name(typeName)
00104 {
00105 StaticBinding::publish( exec, this, ObjectFactory::methods() );
00106
00107 m_owner = CPPOwned;
00108 m_value = new Pointer<T>(ptr);
00109 }
00110
00111 virtual ~ObjectBinding();
00112
00113 const char *typeName() const;
00114
00118 template <typename T>
00119 T *object() const
00120 {
00121 if( m_value )
00122 return pointer_cast<T>(m_value);
00123 else
00124 return 0;
00125 }
00126
00127 void *voidStar() const
00128 {
00129 return m_value->voidStar();
00130 }
00131
00132 template <typename T>
00133 void setObject( T *ptr )
00134 {
00135 if( m_owner == JSOwned )
00136 {
00137
00138 m_value->cleanup();
00139 }
00140 delete m_value;
00141 m_value = new Pointer<T>(ptr);
00142 }
00143
00144 KJS::UString toString( KJS::ExecState *exec ) const;
00145 KJS::UString className() const;
00146 KJS::JSType type() const;
00147
00148 Ownership ownership() const;
00149 void setOwnership( Ownership owner );
00150
00151 };
00152
00157 template< typename T>
00158 T * extractObject( KJS::ExecState *exec, KJS::JSValue *arg, T *defaultValue )
00159 {
00160 if( !arg )
00161 return defaultValue;
00162 else
00163 {
00164 T *returnValue = 0;
00165 KJSEmbed::ObjectBinding *imp = KJSEmbed::extractBindingImp<KJSEmbed::ObjectBinding>(exec, arg );
00166 if( imp )
00167 {
00168
00169
00170
00171 returnValue = (T *)imp->voidStar();
00172 }
00173 if( returnValue )
00174 return returnValue;
00175 else
00176 return defaultValue;
00177 }
00178 }
00179
00184 template< typename T>
00185 T * extractObject( KJS::ExecState *exec, const KJS::List &args, int idx, T *defaultValue = 0L)
00186 {
00187 if( args.size() > idx )
00188 {
00189 return extractObject<T>( exec, args[idx], defaultValue );
00190 }
00191 else
00192 return defaultValue;
00193 }
00194
00199 template< typename T>
00200 KJS::JSValue *createObject(KJS::ExecState *exec, const KJS::UString &className, const T *value, KJSEmbed::ObjectBinding::Ownership owner = KJSEmbed::ObjectBinding::JSOwned )
00201 {
00202 if ( 0 == value )
00203 return KJS::jsNull();
00204
00205 KJS::JSObject *parent = exec->dynamicInterpreter()->globalObject();
00206 KJS::JSObject *returnValue = StaticConstructor::construct( exec, parent, className );
00207 if( returnValue )
00208 {
00209
00210 KJSEmbed::ObjectBinding *imp = extractBindingImp<KJSEmbed::ObjectBinding>(exec, returnValue );
00211 if( imp )
00212 {
00213 imp->setOwnership( KJSEmbed::ObjectBinding::JSOwned );
00214 imp->setObject( value );
00215 imp->setOwnership( owner );
00216 }
00217 else
00218 {
00219 throwError(exec, KJS::TypeError, i18n("%1 is not an Object type", className.ascii()));
00220 return KJS::jsNull();
00221 }
00222 }
00223 else
00224 {
00225 throwError(exec, KJS::GeneralError, "Could not construct value");
00226
00227 return KJS::jsNull();
00228 }
00229
00230 return returnValue;
00231 }
00232
00233 template< typename T >
00234 T extractParameter( KJS::ExecState *exec, KJS::JSValue *arg, const T &defaultValue )
00235 {
00236 if( !arg )
00237 return defaultValue;
00238 else
00239 {
00240 switch (arg->type())
00241 {
00242 case KJS::NumberType:
00243 return extractInt(exec, arg, defaultValue);
00244 break;
00245 case KJS::BooleanType:
00246 return extractBool(exec, arg, 0);
00247 break;
00248 case KJS::UnspecifiedType:
00249 case KJS::UndefinedType:
00250 case KJS::NullType:
00251 case KJS::GetterSetterType:
00252 case KJS::StringType:
00253 return defaultValue;
00254 break;
00255 }
00256
00257 KJS::JSObject* object = arg->toObject(exec);
00258 if(object->inherits(&VariantBinding::info))
00259 {
00260 return extractVariant<T>(exec, arg, defaultValue);
00261 }
00262 else if(object->inherits(&ObjectBinding::info))
00263 {
00264 return extractObject<T>(exec, arg, defaultValue);
00265 }
00266 else
00267 return defaultValue;
00268 }
00269 }
00270 }
00271 #endif
00272
00273