Initialize Tizen 2.3
[framework/appfw/app-core.git] / include / SLP_Appcore_PG.h
1 /*
2  *  app-core
3  *
4  * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Contact: Jayoun Lee <airjany@samsung.com>, Sewook Park <sewook7.park@samsung.com>, Jaeho Lee <jaeho81.lee@samsung.com>
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  * http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  *
20  */
21
22  
23 /**
24  @ingroup SLP_PG
25  @defgroup SLP_PG_APPCORE Application Model and Appcore
26  @{
27
28 <h1 class="pg">Introduction</h1>
29
30 <h2 class="pg">Purpose of this document</h2>
31  This document demonstrates the basic steps needed to develop application(EFL or GTK) using appcore module in the SLP(Samsung Linux Platform). The document provides a brief introduction to the appcore architecture and explains application life-cycle of appcore. Programmers should develop their applications(EFL or GTK) based on the appcore module. The sample applications can be studied and can be used to develop other applications.
32
33 <h2 class="pg">Features</h2>
34 - Support EFL and GTK(including STK) application's basic function
35 - Support internalization
36 - Support rotation function
37 - Support power state function
38
39
40
41 <h1 class="pg">Components of Appcore</h3>
42 @image html SLP_Appcore_PG_overview.png
43
44 - Appcore EFL(libappcore-efl.so)
45   - It provides appcore_efl_main() which includes elm_init(), elm_run(), and other initializations for EFL application
46   - Refer to appcore-efl.h
47 - Appcore common(libappcore-common.so)
48   - It provides useful rotation function to control sensor’s rotation operation in application
49   - It provides useful function to process internalization based on GNU gettext
50   - It provides useful function to control power-state in application
51   - Refer to appcore-common.h
52 - Libraries used by Appcore
53   - EFL and GTK(STK) is a graphic widget library
54   - Sensor for supporting rotation
55   - AUL for application's life-cycle
56   - RUA for task manager
57   - Vconf for system events (such as low battery, low memory).
58 @}
59  @defgroup SLP_PG_APPCORE1 1.Application's life-cycle
60  @ingroup SLP_PG_APPCORE
61  @{
62
63 <h1 class="pg">Application's life-cycle</h2>
64 Appcore provides basic life-cycle like the following to manage application in SLP
65 <table>
66   <tr>
67     <td> @image html SLP_Appcore_PG_lifecycle.png </td>
68     <td>
69       <table>
70         <tr>
71           <th>Operation</th>
72           <th>Description</th>
73         </tr>
74         <tr>
75           <td>CREATE</td>
76           <td>Called once before the main loop. Initialize the application such as window creation, data structure allocation, and etc.</td>
77         </tr>
78         <tr>
79           <td>RESET</td>
80           <td>Called at the first idler and every "relaunch" message. Reset the application states and data structures.</td>
81         </tr>
82         <tr>
83           <td>PAUSE</td>
84           <td>Called when the entire window in this application are invisible. Recommend to suspend the actions related to the visibility.</td>
85         </tr>
86         <tr>
87           <td>RESUME</td>
88           <td>Called when one of the windows in this application is visible. Resume the paused actions.</td>
89         </tr>
90         <tr>
91           <td>TERMINATE</td>
92           <td>Called once after the main loop. Release the resources.</td>
93         </tr>
94       </table> 
95     </td>
96   </tr>
97 </table>
98 Call the main function (appcore_efl_main() with struct appcore_ops filled with the proper function pointers. The functions are called by Appcore at the proper situation.
99 @code
100 struct appcore_ops {
101         void *data; // Callback data
102         int (*create)(void *); // Called before main loop 
103         int (*terminate)(void *); // Called after main loop 
104         int (*pause)(void *); // Called when every window goes back
105         int (*resume)(void *); // Called when any window comes on top
106         int (*reset)(bundle *, void *); // Called at the first idler and every relaunching
107 };
108 @endcode
109
110 @}
111  @defgroup SLP_PG_APPCORE2 2.Appcore event handling
112  @ingroup SLP_PG_APPCORE
113  @{
114
115 <h1 class="pg">Appcore event handling</h2>
116 An Application should perform an action when a system change occurs, such as the battery level goes low. Appcore provides APIs to handle the system changes notified by other frameworks and managers. The following figure shows the relationship between events and callback functions.
117
118 @image html SLP_Appcore_PG_events.png 
119
120 Appcore provides appcore_set_event_callback() to handle events from the system. If you set the callback function, it will be called when the event received. Otherwise, Appcore does default behavior which is defined as following.
121 <table>
122   <tr>
123     <th>Event</th>
124     <th>Description</th>
125     <th>Default behavior</th>
126   </tr>
127   <tr>
128     <td>APPCORE_EVENT_LOW_MEMORY</td>
129     <td>A system memory goes low</td>
130     <td>call malloc_trim() to enforce giving back the freed memory</td>
131   </tr>
132   <tr>
133     <td>APPCORE_EVENT_LOW_BATTERY</td>
134     <td>A system is out of battery</td>
135     <td>Quit the main loop</td>
136   </tr>
137   <tr>
138     <td>APPCORE_EVENT_LANG_CHANGE</td>
139     <td>A system's language setting is changed</td>
140     <td>Reset the environment variable "LANG". This has influence on the function related to internationalization</td>
141   </tr>
142 </table>
143
144
145 @}
146  @defgroup SLP_PG_APPCORE3 3.Internationalization
147  @ingroup SLP_PG_APPCORE
148  @{
149
150 <h1 class="pg">Internationalization</h3>
151 SLP platform uses GNU gettext for Internationalization.
152 The process of using gettext is as follows:
153 -# Marking any phrases to be translated using gettext(“phrase”) or gettext_noop(“phrase”)
154 -# Generating a <I>po</I> file by extracting marked phrases using a <I>xgettext</I> command.
155 -# Modifying the <I>po</I> file and entering a translated phrase for the corresponding phrase.
156 -# Compiling a <I>po</I> file into a <I>mo</I>  file using a <I>msgfmt</I> command.
157 -# Installing <I>mo</I> files into proper locale directories.
158 -# gettext() returns a properly translated phrase while an application is running.
159
160 For example, we have the following source code
161 @code
162 printf(“%s\n”, gettext(“Hello”));
163 @endcode
164
165 Then, as you can see, we can have the following po file using xgettext,
166 @code
167 #: hello.c:41
168 msgid "Hello"
169 msgstr ""
170 @endcode
171
172 And we can enter a translated phrase as the following,
173 @code
174 #: hello.c:41
175 msgid "Hello"
176 msgstr "안녕하세요" // Hello in Korean
177 @endcode
178
179 Finally we generate and install a mo file. In doing so, an application will print out "안녕하세요" instead of "Hello", if the applied language is Korean.
180
181 appcore_set_i18n() has been introduced to achieve an internationalization which requires information on a mo file's name and its installed directory.
182 @code
183 int appcore_set_i18n(const char *domainname, const char *dirname)
184 @endcode
185
186 The first parameter, <I>domainname</I>, a mo file’s name and the second one, <I>dirname</I>, is the directory.<br>
187 In general, a mo file will be installed in the following fashion, <I>dirname/locale/category/domainname.mo</I>. <I>locale</I> is a locale’s name, such as ‘ko’ and ‘ja’, and category is LC_MESSAGES. For instance, a mo file has been installed in /usr/share/locale/ko/LC_MESSAGES/example.mo, and then <I>dirname</I> becomes /usr/share/locale.<br>
188 Typically, mo files will be installed in ${prefix}/share/locale.
189
190 Generally the following macros are defined for easy to use gettext()
191 @code
192 #define _(str) gettext(str)
193 #define gettext_noop(str) (str)
194 #define N_(str) gettext_noop(str)
195 @endcode
196
197 N_() macro only extracts any marked phrases using xgettext command, it will not do anything in the action. This macro is used to handle an array of phrases. Since gettext() cannot be called in declaration of an array, we let N_() macro extract phrases and then call gettext(). Let’s look at the following example.
198
199 @code
200 static const char *messages[] = {
201         N_(“Hello”),
202         N_(“World”)
203 };
204
205 printf(“Message: %s\n”, _(messages[0]);
206
207 @endcode
208
209 In doing so, we now can handle phrases in an array as same as we do for the following.
210
211 @code
212 printf(“Message: %s\n”, _(“Hello”);
213 @endcode
214
215 For more details, refer to GNU gettext manual (http://www.gnu.org/software/gettext/manual/gettext.html)
216
217 @}
218  @defgroup SLP_PG_APPCORE4 4.Rotation
219  @ingroup SLP_PG_APPCORE
220  @{
221
222 <h1 class="pg">Rotation</h3>
223 An Application can display its UI in either landscape or portrait mode. The application registers to receive rotation events from the system with the appcore_set_rotation_cb() API. The system automatically calls the registered user's callback whenever the sensor framework detects that the current rotation status has changed. This continues until appcore_unset_rotation_cb() is called.
224
225 @code
226 enum appcore_rm {
227         APPCORE_RM_UNKNOWN,
228         APPCORE_RM_PORTRAIT_NORMAL , // Portrait mode
229         APPCORE_RM_PORTRAIT_REVERSE , // Portrait upside down mode 
230         APPCORE_RM_LANDSCAPE_NORMAL , // Left handed landscape mode
231         APPCORE_RM_LANDSCAPE_REVERSE ,  // Right handed landscape mode 
232 };
233
234 int appcore_set_rotation_cb(int (*cb)(enum appcore_rm, void *), void *data);
235 int appcore_unset_rotation_cb(void);
236 int appcore_get_rotation_state(enum appcore_rm *curr);
237 @endcode
238
239 <I>enum appcore_rm</I> has portrait, portrait upside down, left handed landscape, and right handed landscape mode. The following is an each mode.
240 @image html SLP_Appcore_PG_rotation.png
241
242 When the registered callback is called, it receives the current mode state as the first argument. According to the received mode state, the application should rotate the window, resize window to changed screen size and composite the screen.
243
244 @}
245  @defgroup SLP_PG_APPCORE5 5.Using code template
246  @ingroup SLP_PG_APPCORE
247  @{
248
249 <h1 class="pg">Using code template</h1>
250 We provide a code template for reference and convenience. You can generate a code template using the script "app-gen.sh" which is included in the <I>app-template</I> package.
251
252 The usage as follow:
253 @code
254 # app-gen.sh
255 Usage)  app-gen.sh dest app_name [EFL|GTK] 
256         app_name does not support _ string because of debian usage."
257
258 ex) 
259  EFL application: 
260   # app-gen.sh ~/efl_app MyApp
261
262  GTK application: 
263   # app-gen.sh /home/app/gtk_app TestApp GTK
264
265 @endcode
266
267 Let's make a simple application using template
268 -# Install <I>app-template</I> package
269 @code
270 # apt-get install app-template
271 @endcode
272 -# Generate a code template
273 @code
274 # app-gen.sh ~/apps/simple simple EFL
275 @endcode
276 -# Build a package
277 @code
278 # cd ~/apps/simple
279 # dpkg-buildpackage -sa -rfakeroot
280 @endcode
281 @}
282  @defgroup SLP_PG_APPCORE6 6.Example: EFL Apps
283  @ingroup SLP_PG_APPCORE
284  @{
285
286 <h1 class="pg">Example: EFL application</h1>
287
288 Header example
289 @code
290 12 #ifndef __APP_COMMON_H__
291 13 #define __APP_COMMON_H__
292 14 
293 15 #include <Elementary.h>
294 16 
295 17 #if !defined(PACKAGE)
296 18 #  define PACKAGE "example"  // for appcore_set_i18n()
297 19 #endif
298 20 
299 21 #if !defined(LOCALEDIR)
300 22 #  define LOCALEDIR "/opt/apps/com.slp.example/share/locale" // for appcore_set_i18n()
301 23 #endif
302 24 
303 25 #if !defined(EDJDIR)
304 26 #  define EDJDIR "/opt/apps/com.slp.example/share/edje"
305 27 #endif
306 28 
307 29 #define EDJ_FILE EDJDIR "/" PACKAGE ".edj"
308 30 #define GRP_MAIN "main"
309 31 
310 32 struct appdata
311 33 {
312 34         Evas_Object *win;
313 35         Evas_Object *ly_main;
314 36 
315 37         // add more variables here
316 38 };
317 39 
318 40 #endif // __APP_COMMON_H__ 
319 @endcode
320
321 Source example
322 @code
323 12 #include <stdio.h>
324 13 #include <appcore-efl.h>
325 14 #include <Ecore_X.h>
326 15 
327 16 #include "example.h"
328 17 
329 18 struct text_part {   // this for internationalization
330 19         char *part;
331 20         char *msgid;
332 21 };
333 22 
334 23 static struct text_part main_txt[] = {
335 24         { "txt_title", N_("Application template"), },
336 25         { "txt_mesg", N_("Click to exit"), },  // N_() is do nothing. Only for extracting the string
337 26 };
338 27
339 28
340 29 static void win_del(void *data, Evas_Object *obj, void *event)
341 30 {
342 31         elm_exit();
343 32 }
344 33 
345 34 static void main_quit_cb(void *data, Evas_Object *obj,
346 35                 const char *emission, const char *source)
347 36 {
348 37         elm_exit();
349 38 }
350 39 
351 40 static void update_ts(Evas_Object *eo, struct text_part *tp, int size)
352 41 {
353 42         int i;
354 43 
355 44         if (eo == NULL || tp == NULL || size < 0)
356 45                 return;
357 46 
358 47         for (i = 0; i < size; i++) {
359 48                 if (tp[i].part && tp[i].msgid)
360 49                         edje_object_part_text_set(eo,
361 50                                         tp[i].part, _(tp[i].msgid)); // _() return translated string
362 51         }
363 52 }
364 53 
365 54 static int lang_changed(void *data) // language changed callback
366 55 {
367 56         struct appdata *ad = data;
368 57 
369 58         if (ad->ly_main == NULL)
370 59                 return 0;
371 60 
372 61         update_ts(elm_layout_edje_get(ad->ly_main), main_txt,
373 62                         sizeof(main_txt)/sizeof(main_txt[0]));
374 63 
375 64         return 0;
376 65 }
377 66 
378 67 static int rotate(enum appcore_rm m, void *data) // rotation callback
379 68 {
380 69         struct appdata *ad = data;
381 70         int r;
382 71 
383 72         if (ad == NULL || ad->win == NULL)
384 73                 return 0;
385 74 
386 75         switch(m) {
387 76         case APPCORE_RM_PORTRAIT_NORMAL:
388 77                 r = 0;
389 78                 break;
390 79         case APPCORE_RM_PORTRAIT_REVERSE:
391 80                 r = 180;
392 81                 break;
393 82         case APPCORE_RM_LANDSCAPE_NORMAL:
394 83                 r = 270;
395 84                 break;
396 85         case APPCORE_RM_LANDSCAPE_REVERSE:
397 86                 r = 90;
398 87                 break;
399 88         default:
400 89                 r = -1;
401 90                 break;
402 91         }
403 92 
404 93         if (r >= 0) // Using this API, you can implement the rotation mode easily
405 94                 elm_win_rotation_with_resize_set(ad->win, r);
406 95 
407 96         return 0;
408 97 }
409 98 
410 99 static Evas_Object* create_win(const char *name)
411 100 {
412 101         Evas_Object *eo;
413 102         int w, h;
414 103 
415 104         eo = elm_win_add(NULL, name, ELM_WIN_BASIC);
416 105         if (eo) {
417 106                 elm_win_title_set(eo, name);
418 107                 elm_win_borderless_set(eo, EINA_TRUE);
419 108                 evas_object_smart_callback_add(eo, "delete,request",
420 109                                 win_del, NULL);
421 110                 ecore_x_window_size_get(ecore_x_window_root_first_get(), // get root window(screen) size
422 111                                 &w, &h);
423 112                 evas_object_resize(eo, w, h);
424 113         }
425 114 
426 115         return eo;
427 116 }
428 117 
429 118 static Evas_Object* load_edj(Evas_Object *parent, const char *file,
430 119                 const char *group)
431 120 {
432 121         Evas_Object *eo;
433 122         int r;
434 123 
435 124         eo = elm_layout_add(parent);
436 125         if (eo) {
437 126                 r = elm_layout_file_set(eo, file, group);
438 127                 if (!r) {
439 128                         evas_object_del(eo);
440 129                         return NULL;
441 130                 }
442 131 
443 132                 evas_object_size_hint_weight_set(eo,
444 133                                 EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
445 134         }
446 135 
447 136         return eo;
448 137 }
449 138 
450 139 static int app_create(void *data)
451 140 {
452 141         struct appdata *ad = data;
453 142         Evas_Object *win;
454 143         Evas_Object *ly;
455 144         int r;
456 145 
457 146         // create window 
458 147         win = create_win(PACKAGE);
459 148         if (win == NULL)
460 149                 return -1;
461 150         ad->win = win;
462 151 
463 152         // load edje 
464 153         ly = load_edj(win, EDJ_FILE, GRP_MAIN);
465 154         if (ly == NULL)
466 155                 return -1;
467 156         elm_win_resize_object_add(win, ly); // This can make the EDJE object fitted in window size
468 157         edje_object_signal_callback_add(elm_layout_edje_get(ly),
469 158                         "EXIT", "*", main_quit_cb, NULL);
470 159         ad->ly_main = ly;
471 160         evas_object_show(ly);
472 161 
473 166         lang_changed(ad); // call the language changed callback to update strings
474 167 
475 168         evas_object_show(win);
476 169 
477 170         // add system event callback 
478 171         appcore_set_event_callback(APPCORE_EVENT_LANG_CHANGE,
479 172                         lang_changed, ad);
480 173 
481 174         appcore_set_rotation_cb(rotate, ad); // set rotation callback
482 175 
483 176         // appcore measure time example 
484 177         printf("from AUL to %s(): %d msec\n", __func__,
485 178                         appcore_measure_time_from("APP_START_TIME"));
486 179 
487 180         appcore_measure_start();
488 181         return 0;
489 182 }
490 183 
491 184 static int app_terminate(void *data) // terminate callback
492 185 {
493 186         struct appdata *ad = data;
494 187 
495 188         if (ad->ly_main)
496 189                 evas_object_del(ad->ly_main);
497 190 
498 191         if (ad->win)
499 192                 evas_object_del(ad->win);
500 193 
501 194         return 0;
502 195 }
503 196 
504 197 static int app_pause(void *data) // pause callback
505 198 {
506 199         struct appdata *ad = data;
507 200 
508 201         return 0;
509 202 }
510 203 
511 204 static int app_resume(void *data) // resume callback
512 205 {
513 206         struct appdata *ad = data;
514 207 
515 208         return 0;
516 209 }
517 210 
518 211 static int app_reset(bundle *b, void *data) // reset callback
519 212 {
520 213         struct appdata *ad = data;
521 214 
522 215         // appcore measure time example 
523 216         printf("from AUL to %s(): %d msec\n", __func__,
524 217                         appcore_measure_time_from("APP_START_TIME"));
525 218         printf("from create to %s(): %d msec\n", __func__,
526 219                         appcore_measure_time());
527 220 
528 221         if (ad->win)
529 222                 elm_win_activate(ad->win); // You should make one of the window on top
530 223 
531 224         return 0;
532 225 }
533 226 
534 227 int main(int argc, char *argv[])
535 228 {
536 229         struct appdata ad;
537 230         struct appcore_ops ops = {  // fill the appcore_ops with callback functions
538 231                 .create = app_create,
539 232                 .terminate = app_terminate,
540 233                 .pause = app_pause,
541 234                 .resume = app_resume,
542 235                 .reset = app_reset,
543 236         };
544 237 
545 238         // appcore measure time example 
546 239         printf("from AUL to %s(): %d msec\n", __func__,
547 240                         appcore_measure_time_from("APP_START_TIME"));
548 241 
549 242         memset(&ad, 0x0, sizeof(struct appdata));
550 243         ops.data = &ad;
551 244 
552 245         return appcore_efl_main(PACKAGE, &argc, &argv, &ops); // start mainloop
553 246 }
554 @endcode
555
556  @}
557 **/