summaryrefslogtreecommitdiff
path: root/pages/develop/legacy/tutorial/genlist/modifications.txt
blob: e8e10c682f1a5162fc8d39c7161dfc1255ba8bb4 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
~~Title: Genlist Modifications~~
==== Genlist Modifications ====

=== Choosing Another Item Style to Add or Remove Parts ===

As mentioned above, the number of parts to fill depends on the item style that
is chosen when adding a new item. This is simply a matter of setting the right
value when filling the ''Elm_Genlist_Item_Class'' struct:

<code c>
itc->item_style = "default";
</code>

The Genlist Widget lists all available item styles:
  * default
  * default_style - The text part is a textblock
  * double_label
  * icon_top_text_bottom
  * group_index
  * one_icon - Only 1 icon at left
  * end_icon - Only 1 icon at end/right
  * no_icon - No icon at end/right
  * full - Only 1 icon, elm.swallow.content, which consumes whole area of genlist item


Further customization is achieved by modifying the theme as explained in the
[[/develop/legacy/program_guide/edje_pg|Edje guide]].

In case the customization is only visual, it is good practice to keep the same
item style names for new themes. This makes it possible to change theme and
keep the code the same while also retaining the same overall item placement.

==== Using Item Modes ====

So far the genlist examples have all featured bare lists while the genlist
widget is able to display trees or even a "group" mode where scrolling keeps
the item at the top of the widget until another group comes and replaces it.

//**__Group Mode__**//

The group mode makes it possible to keep an element visible as long as one of
its children is visible. This is most useful for "title" items.

Mark some elements as ''ELM_GENLIST_ITEM_GROUP'' and use the returned
''Elm_Object_Item'' to establish the parent-children relationship when adding the
children items.

Since there are two kind of items, create two item classes. Give them
different styles and callback functions. The callback functions are visible in
the example, they have no functionalities:

<code c>
Elm_Genlist_Item_Class *_itc_child = elm_genlist_item_class_new();
_itc->item_style        = "default_style";
_itc->func.text_get     = _genlist_text_get_size;
_itc->func.content_get  = _genlist_content_get_bg;
_itc->func.state_get    = NULL;
_itc->func.del          = NULL;

Elm_Genlist_Item_Class *_itc_parent = elm_genlist_item_class_new();
_itc2->item_style       = "default_style";
_itc2->func.text_get    = _genlist_text_get_nosize;
_itc2->func.content_get = _genlist_content_get_icon;
_itc2->func.state_get   = NULL;
_itc2->func.del         = NULL;
</code>

Then add a group header and follow it with 10 children. This is repeated 10
times.

The parent has type ''ELM_GENLIST_ITEM_GROUP'' while the children have type
''ELM_GENLIST_ITEM_NONE''.

The other important point is that the value returned by
''elm_genlist_item_append()'' is stored in it and then sent to the
''elm_genlist_item_append()'' call that adds the children. This creates the
parent-children relationship.

<code c>
for (i = 0; i < 1000; i++)
  {
     it = elm_genlist_item_append(list, _itc_parent,
        (void *)(uintptr_t) (10 * i),
        NULL,
        ELM_GENLIST_ITEM_GROUP,
        NULL,
        NULL
     );
     for (j = 0; j < 10; j++)
       {
          elm_genlist_item_append(list, _itc_child,
             (void *)(uintptr_t) (10 * i + j),
             it, //parent item
             ELM_GENLIST_ITEM_NONE,
             NULL,
             NULL
          );
       }
  }
</code>

//**__Tree Mode__**//

Like group mode, tree mode uses the parenting relationship with other items.
Unlike group mode, the child elements are created on-demand when their parent
is expanded and deleted when it is contracted. This is done by using smart
callbacks: ''expand,request'', ''expanded'', ''contract,request'', and
''contracted''. Like any smart callback, they are registered through
''evas_object_smat_callback_add'' on the genlist object:


<code c>
    evas_object_smart_callback_add(list, "expand,request",
            _tree_item_expand_request, _itc_parent);
    evas_object_smart_callback_add(list, "expanded", _tree_item_expanded,
            _itc_child);

    evas_object_smart_callback_add(list, "contract,request",
            _tree_item_contract_request, _itc_child);
    evas_object_smart_callback_add(list, "contracted", _tree_item_contracted,
            NULL);
</code>

The callbacks ''expand,request'' and ''contract,request'' do only one thing:
decide whether the element is expanded or contracted. This is done by using
''elm_genlist_item_expanded_set()'' function; if it changes the expansion
status of the item, the next callback is called (either ''expanded'' or
''contracted'' , depending on whether it was an ''expand,request'' or
''contract,request'' event). A minimal implementation of these callbacks is
therefore:

<code c>
static void
_tree_item_expand_request(void *data, Evas_Object *o, void *event_info)
{
    Elm_Object_Item *it = (Elm_Object_Item*) event_info;

    elm_genlist_item_item_class_update(it, data);

    elm_genlist_item_expanded_set(it, EINA_TRUE);
}
</code>

<note>
The example above has an extra line: the call to ''elm_genlist_item_item_class_update()''. It changes the item style and is explained in the [[/tutorial/genlist/modifications#Using_Other_APIs|Changing the item class of an item after its creation section]].^
</note>

<code c>
static void
_tree_item_contract_request(void *data, Evas_Object *o, void *event_info)
{
    Elm_Object_Item *it = (Elm_Object_Item*) event_info;

    elm_genlist_item_item_class_update(it, data);

    elm_genlist_item_expanded_set(it, EINA_FALSE);
}
</code>

As said above, once the genlist item status is set to ''expanded'', the
expanded event is triggered and it is the duty of a callback for that event to
populate the list with the item's children. This relies on the ''parent''
parameter of functions like ''elm_genlist_item_append()'', like for the group
mode.

The function below is a callback implementation for the ''expanded'' event. It
adds items that are built similarly to previous items, the only change is the
parent parameter which is not NULL. Conveniently, the
parent''Elm_Object_Item'' and ''Elm_Genlist_Item_Class'' pointers that are passed to the
''elm_genlist_item_append()'' function are given in the ''event_info'' and
''data'' callback and need to be cast.

<code c>
static void
_tree_item_expanded(void *data, Evas_Object *o, void *event_info)
{
    Elm_Object_Item *it_parent = (Elm_Object_Item*) event_info;
    int i_parent = (int)(uintptr_t)elm_object_item_data_get(it_parent);
    Elm_Object_Item *list = o;
    Elm_Genlist_Item_Class *itc = data;

    int i;
    for (i = 0; i < 10; i++)
        {
            elm_genlist_item_append(list, itc,
                    (void *)(uintptr_t) (i + i_parent),
                    it_parent,
                    ELM_GENLIST_ITEM_NONE,
                    NULL,
                    NULL
                    );
        }
}
</code>

The following code has the callback function for the ''contracted'' event. It
imply calls ''elm_genlist_item_subitems_clear()'' to clear all children (including
their own children if they have any) of the given item. Again, the item that
is being contracted is available through the ''event_info'' parameter to the
callback.

<code c>
static void
_tree_item_contracted(void *data, Evas_Object *o, void *event_info)
{
    Elm_Object_Item *it_parent = (Elm_Object_Item*) event_info;

    elm_genlist_item_subitems_clear(it_parent);
}
</code>

//**__Mixing Group and Tree Modes__**//

A common UI design is to mix group and tree modes. It allows for a tree
behavior while also keeping the group header item. The EFLs do not do any
magic here and the way to get such a behavior is to create an item of type
group, an item of type tree which parent is the group item. Then add the
callbacks to populate the children of the tree item in the regular way.

=== Using Other APIs ===

//**__Homogeneous Item Size__**//

Because of the scroller, the actual height and/or width of the genlist must be
computed. This means summing the sizes of all the items, the sizes must be
computed. This obviously has a cost and slows down adding items to the
genlist.

The ''elm_genlist_homogeneous_set()'' function alleviates this issue by
assuming all the items are the same size as the first one of the list. It
speeds up large insertions. However, it may lead to serious graphical issues
if the items are not actually the same size. Use with care.

//**__Changing the Item Class of an Item After Its Creation__**//

Changing the item class of a widget is an easy way to change the appearance
upon selection or others actions of the user. This is done by calling
''elm_genlist_item_class_update()'' :

<code c>
static void
_tree_item_expand_request(void *data, Evas_Object *o, void *event_info)
{
    Elm_Object_Item *it = (Elm_Object_Item*) event_info;

    elm_genlist_item_item_class_update(it, data);

    elm_genlist_item_expanded_set(it, EINA_TRUE);
}
</code>
\\
//**__The whole code__**// : {{/code_c/tutorial/genlist/modifications_genlist.c}}