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