2008-08-18 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 void my_atk_object_add_child(MyAtkObject* parent, MyAtkObject* child)
9 {
10     g_ptr_array_add(parent->children, child);
11     g_object_ref_sink(child);
12
13     atk_object_set_parent(ATK_OBJECT(child), ATK_OBJECT(parent));
14     
15     g_signal_emit_by_name(parent, "children-changed::add",
16         parent->children->len - 1, child);
17 }
18
19 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     g_return_if_fail(parent != NULL);
37
38     MyAtkObject *self = MY_ATK_OBJECT(accessible);
39     AtkObject *parent_old = (atk_object_get_parent(accessible));
40     
41     if(parent_old == parent)
42     {
43         //nothing to do because parent does not change
44         return;
45     }
46     
47     //set field 'parent' in child using 'base-method'
48     atk_object_parent_class->set_parent(accessible, parent);
49     
50     if(parent_old != NULL)
51     {
52         my_atk_object_remove_child((MyAtkObject*)parent_old, self);
53     }
54 }
55
56 static gint my_atk_object_get_n_children(AtkObject *accessible)
57 {
58     return MY_ATK_OBJECT(accessible)->children->len;
59 }
60
61 static AtkObject* my_atk_object_ref_child(AtkObject *accessible, gint i)
62 {
63     MyAtkObject *self = MY_ATK_OBJECT(accessible); 
64     if(i < 0 || i >= self->children->len)
65     {
66         printf("ref_child: Incorrect index of child.\n");
67         return NULL;
68     }
69
70     AtkObject* child = (AtkObject*)
71         g_ptr_array_index(self->children, i);
72
73     return (child == NULL) ? NULL : g_object_ref(child);
74 }
75
76 static gint my_atk_object_get_index_in_parent(AtkObject *accessible)
77 {
78     AtkObject *parent = atk_object_get_parent(accessible);
79     if(parent == NULL) return -1;//no parent
80     
81     MyAtkObject *parent_my = MY_ATK_OBJECT(parent);
82
83     int i = parent_my->children->len;
84     for(; i>=0; i--)
85     {
86         if(g_ptr_array_index(parent_my->children,i) == accessible)
87             break;
88     }
89     if(i < 0)printf("Something wrong in parent-child strucutre.\n");
90     return i;//if error, i will be equal to -1
91 }
92
93 //function, needed in instance_finalize()
94 static void my_unref1(gpointer data, gpointer user_data)
95 {
96     g_object_unref(data);
97 }
98
99 static void my_atk_object_instance_finalize(GObject *obj)
100 {
101     MyAtkObject *self = (MyAtkObject*) obj;
102     //unrefs all children
103     g_ptr_array_foreach(self->children, my_unref1, NULL);
104     //then free array (without frees pointers)
105     g_ptr_array_free(self->children, FALSE);
106     //chain to parent class
107     G_OBJECT_CLASS(atk_object_parent_class)->finalize(obj);
108 }
109
110 void my_atk_object_class_init(gpointer g_class, gpointer g_class_data)
111 {
112     AtkObjectClass *atkObjectClass = (AtkObjectClass*)g_class;
113     
114     ((GObjectClass*)g_class)->finalize = my_atk_object_instance_finalize;
115     //set pointers to new functions in table of virtuals functions
116     atkObjectClass->set_parent = my_atk_object_set_parent;
117     atkObjectClass->get_n_children = my_atk_object_get_n_children;
118     atkObjectClass->ref_child = my_atk_object_ref_child;
119     atkObjectClass->get_index_in_parent = my_atk_object_get_index_in_parent;
120
121     atk_object_parent_class = g_type_class_peek_parent(g_class);
122 }
123
124 static void my_atk_object_instance_init(GTypeInstance *obj, gpointer g_class)
125 {
126     MyAtkObject *self = (MyAtkObject*)obj;
127
128     self->children = g_ptr_array_sized_new(10);
129 }
130
131 GType my_atk_object_get_type()
132 {
133     static GType type = 0;
134     if(type == 0)
135     {
136         static const GTypeInfo typeInfo = 
137         {
138             sizeof(MyAtkObjectClass),
139             NULL, //base_init
140             NULL, //base_finalize
141             my_atk_object_class_init, //class_init
142             NULL, //class_finalize
143             NULL, //class_data
144             sizeof(MyAtkObject),
145             0, //n_preallocs
146             my_atk_object_instance_init //instance_init
147         };
148         type = g_type_register_static(ATK_TYPE_OBJECT,"MyAtkObject",&typeInfo,0);
149     }
150     return type;
151 }