Пример #1
0
static VALUE
gobj_s_install_property(int argc, VALUE* argv, VALUE self)
{
    const RGObjClassInfo* cinfo = rbgobj_lookup_class(self);
    gpointer gclass;
    GParamSpec* pspec;
    VALUE pspec_obj, prop_id;

    if (cinfo->klass != self)
        rb_raise(rb_eTypeError, "%s isn't registered class",
                 rb_class2name(self));

    rb_scan_args(argc, argv, "11", &pspec_obj, &prop_id);
    pspec = G_PARAM_SPEC(RVAL2GOBJ(pspec_obj));

    gclass = g_type_class_ref(cinfo->gtype);
    g_object_class_install_property(gclass,
                                    NIL_P(prop_id) ? 1 : NUM2UINT(prop_id),
                                    pspec);
    g_type_class_unref(gclass);

    /* FIXME: define accessor methods */

    return Qnil;
}
Пример #2
0
static VALUE
gobj_s_gobject_new(int argc, VALUE *argv, VALUE self)
{
    const RGObjClassInfo* cinfo = rbgobj_lookup_class(self);
    VALUE params_hash;
    GObject* gobj;
    VALUE result;

    rb_scan_args(argc, argv, "01", &params_hash);

    if (!NIL_P(params_hash))
        Check_Type(params_hash, T_HASH);

    if (cinfo->klass != self)
        rb_raise(rb_eTypeError, "%s isn't registered class",
                 rb_class2name(self));

    gobj = rbgobj_gobject_new(cinfo->gtype, params_hash);
    result = GOBJ2RVAL(gobj);

    // XXX: Ughhhhh
    if (is_gtkobject(gobj)){
        // We can't call gtk_object_sink() here.
        // But hopefully someone will call it in the future.
        //gtk_object_sink(gobj);
    } else {
        g_object_unref(gobj);
    }

    return result;
}
Пример #3
0
static VALUE
rg_initialize(VALUE self)
{
    VALUE rb_class;
    gsize instance_size = 0;

    rb_class = CLASS_OF(self);
    if (RVAL2CBOOL(rb_ivar_defined(rb_class, rb_intern("@size")))) {
        instance_size = NUM2UINT(rb_iv_get(rb_class, "@size"));
    }

    if (instance_size > 0) {
        const RGObjClassInfo *cinfo;
        gpointer instance;

        cinfo = rbgobj_lookup_class(rb_class);
        instance = alloca(instance_size);
        memset(instance, 0, instance_size);
        G_INITIALIZE(self, g_boxed_copy(cinfo->gtype, instance));
    } else {
        rb_raise(rb_eTypeError, "can't initialize %s",
                 rb_class2name(rb_class));
    }

    return Qnil;
}
Пример #4
0
const RGObjClassInfo *
rbgobj_lookup_class(VALUE klass)
{
    VALUE data = rb_hash_aref(klass_to_cinfo, klass);
    if (!NIL_P(data)) {
        RGObjClassInfo* cinfo;
        Data_Get_Struct(data, RGObjClassInfo, cinfo);
        return cinfo;
    }

    if (TYPE(klass) == T_CLASS) {
        VALUE super;
        super = rb_funcall(klass, id_superclass, 0);
        return rbgobj_lookup_class(super);
    }

    rb_raise(rb_eRuntimeError, "can't get gobject class information");
}
static VALUE
interface_s_install_property(VALUE self, VALUE pspec_obj)
{
    const RGObjClassInfo* cinfo = rbgobj_lookup_class(self);
    gpointer ginterface;
    GParamSpec* pspec;

    if (cinfo->klass != self)
        rb_raise(rb_eTypeError, "%s isn't registered class", rb_class2name(self));

    pspec = G_PARAM_SPEC(RVAL2GOBJ(pspec_obj));
    ginterface = g_type_default_interface_ref(cinfo->gtype);
    g_object_interface_install_property(ginterface, pspec);
    g_type_default_interface_unref(ginterface);

    /* FIXME: define accessor methods */
    return Qnil;
}
Пример #6
0
static VALUE
rbgobj_boxed_s_allocate(VALUE klass)
{
    const RGObjClassInfo* cinfo = rbgobj_lookup_class(klass);
    boxed_holder* holder;
    VALUE result;

    if (cinfo->gtype == G_TYPE_BOXED)
        rb_raise(rb_eTypeError, "abstract class");

    result = Data_Make_Struct(klass, boxed_holder, 
                              boxed_mark, boxed_free, holder);
    holder->type  = cinfo->gtype;
    holder->boxed = NULL;
    holder->own   = FALSE;

    return result;
}
Пример #7
0
static VALUE
pspec_s_allocate(VALUE klass)
{
    const RGObjClassInfo* cinfo = rbgobj_lookup_class(klass);
    if (G_TYPE_IS_ABSTRACT(cinfo->gtype))
        rb_raise(rb_eTypeError, "abstract class");

    {
        pspec_holder* holder;
        VALUE result;

        result = Data_Make_Struct(klass, pspec_holder, pspec_mark, pspec_free,
                                  holder);
        holder->instance = NULL;
        holder->cinfo    = NULL;

        return result;
    }
}
Пример #8
0
static VALUE
rg_s_install_style_property(VALUE self, VALUE spec)
{
    const RGObjClassInfo* cinfo = rbgobj_lookup_class(self);
    GtkWidgetClass* gclass;
    GParamSpec* pspec = G_PARAM_SPEC(RVAL2GOBJ(spec));

    if (cinfo->klass != self)
        rb_raise(rb_eTypeError, "%s isn't registered class",
                 rb_class2name(self));

    gclass = (GtkWidgetClass *)g_type_class_ref(cinfo->gtype);
    if (rb_block_given_p()){
        VALUE func = rb_block_proc();
        rb_hash_aset(style_prop_func_table, spec, func);
        gtk_widget_class_install_style_property_parser(gclass, pspec,
                                                       (GtkRcPropertyParser)rc_property_parser);
    } else {
        gtk_widget_class_install_style_property(gclass, pspec);
    }
    return self;
}
Пример #9
0
static VALUE
rg_s_new_bang(int argc, VALUE *argv, VALUE self)
{
    const RGObjClassInfo* cinfo = rbgobj_lookup_class(self);
    VALUE params_hash;
    GObject* gobj;
    VALUE result;

    rb_scan_args(argc, argv, "01", &params_hash);

    if (!NIL_P(params_hash))
        Check_Type(params_hash, RUBY_T_HASH);

    if (cinfo->klass != self)
        rb_raise(rb_eTypeError, "%s isn't registered class",
                 rb_class2name(self));

    gobj = rbgobj_gobject_new(cinfo->gtype, params_hash);
    result = GOBJ2RVAL(gobj);
    g_object_unref(gobj);

    return result;
}
Пример #10
0
static VALUE
type_register(int argc, VALUE* argv, VALUE self)
{
    VALUE type_name, flags;
    volatile VALUE class_init_proc = Qnil;
    GType parent_type;
    GTypeInfo* info;

    rb_scan_args(argc, argv, "03", &type_name, &info, &flags);

    {
        const RGObjClassInfo* cinfo = rbgobj_lookup_class(self);
        if (cinfo->klass == self)
            rb_raise(rb_eTypeError, "already registered");
    }

    {
        VALUE superclass = rb_funcall(self, rb_intern("superclass"), 0);
        const RGObjClassInfo* cinfo = rbgobj_lookup_class(superclass);
        if (cinfo->klass != superclass)
            rb_raise(rb_eTypeError, "super class must be registered to GLib");
        parent_type = cinfo->gtype;
    }

    if (NIL_P(type_name)) {
        VALUE s = rb_funcall(self, rb_intern("name"), 0);

        if (strlen(StringValuePtr(s)) == 0)
            rb_raise(rb_eTypeError, "can't determine type name");

        type_name = rb_funcall(
            rb_eval_string("lambda{|x| x.gsub(/::/,'') }"),
            rb_intern("call"), 1, s);
    }

    {
        GTypeQuery query;
        g_type_query(parent_type, &query);

        info = g_new0(GTypeInfo, 1);
        info->class_size     = query.class_size;
        info->base_init      = NULL;
        info->base_finalize  = NULL;
        info->class_init     = class_init_func;
        info->class_finalize = NULL;
        info->class_data     = (gpointer)class_init_proc;
        info->instance_size  = query.instance_size;
        info->n_preallocs    = 0;
        info->instance_init  = NULL;
        info->value_table    = NULL;
    }

    {
        GType type = g_type_register_static(parent_type,
                                            StringValuePtr(type_name),
                                            info,
                                            NIL_P(flags) ? 0 : NUM2INT(flags));
        G_RELATIVE(self, class_init_proc);

        rbgobj_register_class(self, type, TRUE, TRUE);

        {
            RGObjClassInfo* cinfo = (RGObjClassInfo*)rbgobj_lookup_class(self);
            cinfo->flags |= RBGOBJ_DEFINED_BY_RUBY;
        }

        {
            GType parent = g_type_parent(type);
            const RGObjClassInfo* cinfo =  GTYPE2CINFO(parent);
            VALUE m = rb_define_module_under(self, RubyGObjectHookModule);

            if (! (cinfo->flags & RBGOBJ_DEFINED_BY_RUBY)) {
                rb_define_method(m, "initialize", gobj_initialize, -1);
            }

            rb_include_module(self, m);
        }

        return Qnil;
    }
}
Пример #11
0
void
rbgobj_register_type(VALUE klass, VALUE type_name, GClassInitFunc class_init)
{
    GType parent_type;
    GTypeInfo *info;

    {
        const RGObjClassInfo *cinfo = rbgobj_lookup_class(klass);
        if (cinfo->klass == klass)
            rb_raise(rb_eTypeError,
                     "already registered class: <%s>",
                     RBG_INSPECT(klass));
    }

    {
        VALUE superclass = rb_funcall(klass, rb_intern("superclass"), 0);
        const RGObjClassInfo *cinfo = rbgobj_lookup_class(superclass);
        if (cinfo->klass != superclass)
            rb_raise(rb_eTypeError,
                     "super class must be registered to GLib: <%s>",
                     RBG_INSPECT(superclass));
        parent_type = cinfo->gtype;
    }

    if (NIL_P(type_name)) {
        VALUE klass_name = rb_funcall(klass, rb_intern("name"), 0);

        if (strlen(StringValueCStr(klass_name)) == 0)
            rb_raise(rb_eTypeError,
                     "can't determine type name: <%s>",
                     RBG_INSPECT(klass));

        type_name = rb_funcall(klass_name, rb_intern("gsub"),
                               2,
                               rb_str_new_cstr("::"),
                               rb_str_new_cstr(""));
    }

    {
        GTypeQuery query;
        g_type_query(parent_type, &query);

        /* TODO: Why new?  g_type_register_static() doesn’t retain a copy, so
         * this should be allocated on the stack. */
        info = g_new0(GTypeInfo, 1);
        info->class_size     = query.class_size;
        info->base_init      = NULL;
        info->base_finalize  = NULL;
        info->class_init     = class_init;
        info->class_finalize = NULL;
        info->class_data     = NULL;
        info->instance_size  = query.instance_size;
        info->n_preallocs    = 0;
        info->instance_init  = NULL;
        info->value_table    = NULL;
    }

    {
        GType type = g_type_register_static(parent_type,
                                            StringValueCStr(type_name),
                                            info,
                                            0);

        rbgobj_register_class(klass, type, TRUE, TRUE);

        {
            RGObjClassInfo *cinfo = (RGObjClassInfo *)rbgobj_lookup_class(klass);
            cinfo->flags |= RBGOBJ_DEFINED_BY_RUBY;
        }

        {
            GType parent = g_type_parent(type);
            const RGObjClassInfo *cinfo =  GTYPE2CINFO(parent);
            VALUE initialize_module;

            initialize_module = rb_define_module_under(klass,
                                                       RubyGObjectHookModule);
            if (!(cinfo->flags & RBGOBJ_DEFINED_BY_RUBY)) {
                rbg_define_method(initialize_module,
                                  "initialize", rg_initialize, -1);
            }

            rb_include_module(klass, initialize_module);
        }
    }
}