summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCedric BAIL <cedric.bail@free.fr>2019-01-10 16:40:25 -0800
committerCedric BAIL <cedric.bail@free.fr>2019-01-30 12:06:18 -0800
commitf30c7c6a1ea5f9d6ff369edaebd3cb9cb8b5caac (patch)
tree3033f4f28f1043d05c4589ff7e0f2f005b01416e
parent4aa6285a75ea69a7b608890f4ff44a6aecbf349f (diff)
elementary: add internal Efl_Ui_Model_Average.
This model enable View that require to compute the size of their item to rely on its logic to store all items size independently. It has the same interface as the Homogeneous and should be exchangeable for a View. It provide an average total size at all time. It use Efl.Ui.Model_Exact to do most of the work and is a good example on how to alter a Model logic. Reviewed-by: SangHyeon Jade Lee <sh10233.lee@samsung.com> Differential Revision: https://phab.enlightenment.org/D7661
-rw-r--r--src/Makefile_Elementary.am2
-rw-r--r--src/lib/elementary/efl_ui_model_average.c181
-rw-r--r--src/lib/elementary/efl_ui_model_average.eo19
-rw-r--r--src/lib/elementary/elm_priv.h1
-rw-r--r--src/lib/elementary/meson.build2
5 files changed, 205 insertions, 0 deletions
diff --git a/src/Makefile_Elementary.am b/src/Makefile_Elementary.am
index f9485bb9b7..ed2a629d14 100644
--- a/src/Makefile_Elementary.am
+++ b/src/Makefile_Elementary.am
@@ -179,6 +179,7 @@ elm_private_eolian_files = \
179 lib/elementary/efl_ui_model_size.eo \ 179 lib/elementary/efl_ui_model_size.eo \
180 lib/elementary/efl_ui_model_homogeneous.eo \ 180 lib/elementary/efl_ui_model_homogeneous.eo \
181 lib/elementary/efl_ui_model_exact.eo \ 181 lib/elementary/efl_ui_model_exact.eo \
182 lib/elementary/efl_ui_model_average.eo \
182 $(NULL) 183 $(NULL)
183 184
184# Legacy classes - not part of public EO API 185# Legacy classes - not part of public EO API
@@ -892,6 +893,7 @@ lib_elementary_libelementary_la_SOURCES = \
892 lib/elementary/efl_ui_model_size.c \ 893 lib/elementary/efl_ui_model_size.c \
893 lib/elementary/efl_ui_model_homogeneous.c \ 894 lib/elementary/efl_ui_model_homogeneous.c \
894 lib/elementary/efl_ui_model_exact.c \ 895 lib/elementary/efl_ui_model_exact.c \
896 lib/elementary/efl_ui_model_average.c \
895 $(NULL) 897 $(NULL)
896 898
897 899
diff --git a/src/lib/elementary/efl_ui_model_average.c b/src/lib/elementary/efl_ui_model_average.c
new file mode 100644
index 0000000000..be4dca59a1
--- /dev/null
+++ b/src/lib/elementary/efl_ui_model_average.c
@@ -0,0 +1,181 @@
1#ifdef HAVE_CONFIG_H
2# include <config.h>
3#endif
4
5#include <Elementary.h>
6#include "elm_priv.h"
7
8// This class rely on the parent class to do all the individual holding of value,
9// it only compute the average size of an item and answer for that property alone.
10
11// FIXME: handle child being removed
12typedef struct _Efl_Ui_Model_Average_Data Efl_Ui_Model_Average_Data;
13struct _Efl_Ui_Model_Average_Data
14{
15 Efl_Ui_Model_Average_Data *parent;
16
17 struct {
18 unsigned long long width;
19 unsigned long long height;
20 unsigned long long wseen;
21 unsigned long long hseen;
22 } total;
23
24 Eina_Bool wseen : 1;
25 Eina_Bool hseen : 1;
26};
27
28typedef struct _Efl_Ui_Model_Average_Update Efl_Ui_Model_Average_Update;
29struct _Efl_Ui_Model_Average_Update
30{
31 unsigned long long *total;
32 unsigned long long *seen;
33 unsigned int previous;
34};
35
36static Eina_Value
37_efl_ui_model_average_update(Eo *obj EINA_UNUSED, void *data, const Eina_Value v)
38{
39 Efl_Ui_Model_Average_Update *request = data;
40 unsigned int now;
41
42 if (!eina_value_uint_convert(&v, &now))
43 goto on_error;
44
45 *(request->total) += now - request->previous;
46 if (request->seen) *(request->seen) += 1;
47
48 on_error:
49 return v;
50}
51
52static void
53_efl_ui_model_average_clean(Eo *obj EINA_UNUSED, void *data, const Eina_Future *dead_future EINA_UNUSED)
54{
55 free(data);
56}
57
58static Eina_Future *
59_efl_ui_model_average_prepare(Eo *obj,
60 unsigned long long *total, unsigned long long *seen,
61 const char *property, Eina_Value *value)
62{
63 Efl_Ui_Model_Average_Update *update;
64 Eina_Value *previous;
65 Eina_Future *f;
66
67 update = calloc(1, sizeof (Efl_Ui_Model_Average_Update));
68 if (!update) return efl_loop_future_rejected(obj, ENOMEM);
69
70 previous = efl_model_property_get(obj, property);
71 if (eina_value_type_get(previous) == EINA_VALUE_TYPE_ERROR)
72 {
73 Eina_Error err;
74
75 // Check the case when that property hasn't been set before
76 if (!eina_value_error_convert(previous, &err))
77 goto on_error;
78 if (err != EAGAIN) goto on_error;
79 }
80 else if (!eina_value_uint_convert(previous, &update->previous))
81 goto on_error;
82 eina_value_free(previous);
83
84 update->total = total;
85 update->seen = seen;
86
87 // We have to make the change after we fetch the old value, otherwise, well, no old value left
88 f = efl_model_property_set(efl_super(obj, EFL_UI_MODEL_AVERAGE_CLASS), property, value);
89
90 return efl_future_then(obj, f,
91 .success = _efl_ui_model_average_update,
92 .free = _efl_ui_model_average_clean,
93 .data = update);
94 on_error:
95 eina_value_free(previous);
96 free(update);
97 return efl_loop_future_rejected(obj, EFL_MODEL_ERROR_INCORRECT_VALUE);
98}
99
100static Eina_Future *
101_efl_ui_model_average_efl_model_property_set(Eo *obj, Efl_Ui_Model_Average_Data *pd, const char *property, Eina_Value *value)
102{
103 Eina_Future *f = NULL;
104
105 if (!pd->parent) goto end;
106
107 // In vertical list mode we do not need to compute the average width size
108 /* if (!strcmp(property, _efl_model_property_selfw)) */
109 /* { */
110 /* f = _efl_ui_model_average_prepare(obj, &pd->parent->total.width, */
111 /* pd->wseen ? NULL : &pd->parent->total.wseen, */
112 /* property, value, EINA_TRUE); */
113 /* pd->wseen = EINA_TRUE; */
114 /* } */
115 if (!strcmp(property, _efl_model_property_selfh))
116 {
117 f = _efl_ui_model_average_prepare(obj, &pd->parent->total.height,
118 pd->hseen ? NULL : &pd->parent->total.hseen,
119 property, value);
120 pd->hseen = EINA_TRUE;
121 }
122
123 end:
124 if (!f)
125 f = efl_model_property_set(efl_super(obj, EFL_UI_MODEL_AVERAGE_CLASS), property, value);
126
127 return f;
128}
129
130static inline Eina_Value *
131_efl_ui_model_average_compute(const Eo *obj, Eina_Value *r, unsigned long long total, unsigned long long seen)
132{
133 unsigned int count;
134
135 eina_value_free(r);
136
137 // Protection against divide by zero
138 if (!seen) return eina_value_uint_new(0);
139
140 count = efl_model_children_count_get(obj);
141 // We are doing the multiply first in an attempt to not reduce the precision to early on.
142 return eina_value_uint_new((total * count) / seen);
143}
144
145static Eina_Value *
146_efl_ui_model_average_efl_model_property_get(const Eo *obj, Efl_Ui_Model_Average_Data *pd, const char *property)
147{
148 const Eina_Value_Type *t;
149 Eina_Value *r;
150
151 r = efl_model_property_get(efl_super(obj, EFL_UI_MODEL_AVERAGE_CLASS), property);
152 if (!r) return r;
153
154 // We are checking that the parent class was able to provide an answer to the request for property "Total.Width"
155 // or "Total.Height" which means that we are an object that should compute its size. This avoid computing the
156 // pointer to the parent object.
157 t = eina_value_type_get(r);
158 if (t == EINA_VALUE_TYPE_UINT)
159 {
160 if (!strcmp(property, _efl_model_property_totalh))
161 r = _efl_ui_model_average_compute(obj, r, pd->total.height, pd->total.hseen);
162 // We do not need to average the width in vertical list mode as this is done by the parent class
163 /* if (!strcmp(property, _efl_model_property_totalw)) */
164 /* r = _efl_ui_model_average_compute(obj, r, pd->total.width, pd->total.wseen); */
165 }
166
167 return r;
168}
169
170static Efl_Object *
171_efl_ui_model_average_efl_object_constructor(Eo *obj, Efl_Ui_Model_Average_Data *pd)
172{
173 Eo *parent = efl_parent_get(obj);
174
175 if (parent && efl_isa(parent, EFL_UI_MODEL_AVERAGE_CLASS))
176 pd->parent = efl_data_scope_get(efl_parent_get(obj), EFL_UI_MODEL_AVERAGE_CLASS);
177
178 return efl_constructor(efl_super(obj, EFL_UI_MODEL_AVERAGE_CLASS));
179}
180
181#include "efl_ui_model_average.eo.c"
diff --git a/src/lib/elementary/efl_ui_model_average.eo b/src/lib/elementary/efl_ui_model_average.eo
new file mode 100644
index 0000000000..1af87f986e
--- /dev/null
+++ b/src/lib/elementary/efl_ui_model_average.eo
@@ -0,0 +1,19 @@
1class Efl.Ui.Model_Average extends Efl.Ui.Model_Exact
2{
3 [[Class to be used to store object item size for List/Grid View.
4
5 This model provide the same feature as @Efl.Ui.Model_Exact except for the
6 @Efl.Model.property "$total.width" and "$total.height" which reflect an
7 estimated value of the total size by using the currently know size from its
8 children as an average size for all its children. As more children fill
9 "$self.width" and "$self.height", this model will figure out a more precise
10 answer. Once all children size is known, the result will be exact and the same
11 as @Efl.Ui.Model_Exact.
12
13 This model only supporting vertical list at this point.]]
14
15 implements {
16 Efl.Object.constructor;
17 Efl.Model.property { set; get; }
18 }
19} \ No newline at end of file
diff --git a/src/lib/elementary/elm_priv.h b/src/lib/elementary/elm_priv.h
index a5f187df17..e0b284b6b6 100644
--- a/src/lib/elementary/elm_priv.h
+++ b/src/lib/elementary/elm_priv.h
@@ -72,6 +72,7 @@
72# include "efl_ui_model_size.eo.h" 72# include "efl_ui_model_size.eo.h"
73# include "efl_ui_model_homogeneous.eo.h" 73# include "efl_ui_model_homogeneous.eo.h"
74# include "efl_ui_model_exact.eo.h" 74# include "efl_ui_model_exact.eo.h"
75# include "efl_ui_model_average.eo.h"
75 76
76extern const char *_efl_model_property_itemw; 77extern const char *_efl_model_property_itemw;
77extern const char *_efl_model_property_itemh; 78extern const char *_efl_model_property_itemh;
diff --git a/src/lib/elementary/meson.build b/src/lib/elementary/meson.build
index c4453b7c9e..f9c508de0b 100644
--- a/src/lib/elementary/meson.build
+++ b/src/lib/elementary/meson.build
@@ -340,6 +340,7 @@ priv_eo_files = [
340 'efl_ui_model_size.eo', 340 'efl_ui_model_size.eo',
341 'efl_ui_model_homogeneous.eo', 341 'efl_ui_model_homogeneous.eo',
342 'efl_ui_model_exact.eo', 342 'efl_ui_model_exact.eo',
343 'efl_ui_model_average.eo',
343] 344]
344 345
345priv_eo_file_target = [] 346priv_eo_file_target = []
@@ -911,6 +912,7 @@ elementary_src = [
911 'efl_ui_model_size.c', 912 'efl_ui_model_size.c',
912 'efl_ui_model_homogeneous.c', 913 'efl_ui_model_homogeneous.c',
913 'efl_ui_model_exact.c', 914 'efl_ui_model_exact.c',
915 'efl_ui_model_average.c',
914] 916]
915 917
916elementary_deps = [emile, eo, efl, edje, ethumb, ethumb_client, emotion, ecore_imf, ecore_con, eldbus, efreet, efreet_mime, efreet_trash, eio, atspi, dl, intl] 918elementary_deps = [emile, eo, efl, edje, ethumb, ethumb_client, emotion, ecore_imf, ecore_con, eldbus, efreet, efreet_mime, efreet_trash, eio, atspi, dl, intl]