2008-05-28 Mark Doffman <mark.doffman@codethink.co.uk>
[platform/core/uifw/at-spi2-atk.git] / tests / dummyatk / my-atk-object.c
1
2 #include <atk/atk.h>
3
4 #include "my-atk-object.h"
5
6 static AtkObjectClass *atk_object_parent_class = NULL;
7
8
9 //add/remove child to/from array of parent(for internal use)
10 static void my_atk_object_add_child(MyAtkObject* parent, MyAtkObject* child)
11 {
12     g_ptr_array_add(parent->children, child);
13     g_object_ref(child);
14     
15     g_signal_emit_by_name(parent, "children-changed::add",
16         parent->children->len - 1, child);
17 }
18
19 static void my_atk_object_remove_child(MyAtkObject* parent, MyAtkObject* child)
20 {
21     gint i;
22     for(i = parent->children->len - 1; i >= 0; i--)
23     {
24         if(g_ptr_array_index(parent->children, i) == child) break;
25     }
26     if(i < 0)return;
27
28     g_ptr_array_remove_index(parent->children, i);
29     g_object_unref(child);
30     g_signal_emit_by_name(parent, "children-changed::remove",
31         i, child);
32 }
33
34 static void my_atk_object_set_parent(AtkObject *accessible, AtkObject *parent)
35 {
36     //applicable only with corresponding type of parent
37     g_return_if_fail(parent == NULL || MY_IS_ATK_OBJECT(parent));
38
39     MyAtkObject *self = MY_ATK_OBJECT(accessible);
40     AtkObject *parent_old = (atk_object_get_parent(accessible));
41     
42     if(parent_old == parent)
43     {
44         //nothing to do because parent does not change
45         return;
46     }
47     
48     //set field 'parent' in child using 'base-method'
49     atk_object_parent_class->set_parent(accessible, parent);
50     
51     if(parent_old != NULL)
52     {
53         my_atk_object_remove_child((MyAtkObject*)parent_old, self);
54     }
55     if(parent != NULL)
56     {
57         my_atk_object_add_child((MyAtkObject*)parent, self);
58     }
59 }
60
61 static gint my_atk_object_get_n_children(AtkObject *accessible)
62 {
63     return MY_ATK_OBJECT(accessible)->children->len;
64 }
65
66 static AtkObject* my_atk_object_ref_child(AtkObject *accessible, gint i)
67 {
68     MyAtkObject *self = MY_ATK_OBJECT(accessible); 
69     if(i < 0 || i >= self->children->len)
70     {
71         printf("ref_child: Incorrect index of child.\n");
72         return NULL;
73     }
74
75     AtkObject* child = (AtkObject*)
76         g_ptr_array_index(self->children, i);
77
78     return (child == NULL) ? NULL : g_object_ref(child);
79 }
80
81 static gint my_atk_object_get_index_in_parent(AtkObject *accessible)
82 {
83     AtkObject *parent = atk_object_get_parent(accessible);
84     if(parent == NULL) return -1;//no parent
85     
86     MyAtkObject *parent_my = MY_ATK_OBJECT(parent);
87
88     int i = parent_my->children->len;
89     for(; i>=0; i--)
90     {
91         if(g_ptr_array_index(parent_my->children,i) == accessible)
92             break;
93     }
94     if(i < 0)printf("Something wrong in parent-child strucutre.\n");
95     return i;//if error, i will be equal to -1
96 }
97
98 //function, needed in instance_finalize()
99 static void my_unref1(gpointer data, gpointer user_data)
100 {
101     g_object_unref(data);
102 }
103
104 static void my_atk_object_instance_finalize(GObject *obj)
105 {
106     MyAtkObject *self = (MyAtkObject*) obj;
107     //unrefs all children
108     g_ptr_array_foreach(self->children, my_unref1, NULL);
109     //then free array (without frees pointers)
110     g_ptr_array_free(self->children, FALSE);
111     //chain to parent class
112     G_OBJECT_CLASS(atk_object_parent_class)->finalize(obj);
113 }
114
115 void my_atk_object_class_init(gpointer g_class, gpointer g_class_data)
116 {
117     AtkObjectClass *atkObjectClass = (AtkObjectClass*)g_class;
118     
119     ((GObjectClass*)g_class)->finalize = my_atk_object_instance_finalize;
120     //set pointers to new functions in table of virtuals functions
121     atkObjectClass->set_parent = my_atk_object_set_parent;
122     atkObjectClass->get_n_children = my_atk_object_get_n_children;
123     atkObjectClass->ref_child = my_atk_object_ref_child;
124     atkObjectClass->get_index_in_parent = my_atk_object_get_index_in_parent;
125
126     atk_object_parent_class = g_type_class_peek_parent(g_class);
127 }
128
129 static void my_atk_object_instance_init(GTypeInstance *obj, gpointer g_class)
130 {
131     MyAtkObject *self = (MyAtkObject*)obj;
132
133     self->children = g_ptr_array_sized_new(10);
134 }
135
136 GType my_atk_object_get_type()
137 {
138     static GType type = 0;
139     if(type == 0)
140     {
141         static const GTypeInfo typeInfo = 
142         {
143             sizeof(MyAtkObjectClass),
144             NULL, //base_init
145             NULL, //base_finalize
146             my_atk_object_class_init, //class_init
147             NULL, //class_finalize
148             NULL, //class_data
149             sizeof(MyAtkObject),
150             0, //n_preallocs
151             my_atk_object_instance_init //instance_init
152         };
153         type = g_type_register_static(ATK_TYPE_OBJECT,"MyAtkObject",&typeInfo,0);
154     }
155     return type;
156 }