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