1. Changed license year
[apps/home/mobileprint.git] / mobileprint / smsc / lib / smsc_widget.c
1 /*
2 *  Mobileprint
3 *
4 * Copyright 2013  Samsung Electronics Co., Ltd
5
6 * Licensed under the Flora License, Version 1.1 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9
10 * http://floralicense.org/license/
11
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 *
18 */
19
20 #include <page_preview.h>
21 #include <previewgen.h>
22
23 //#include <pts_debug.h>
24
25 #include "smsc_debug.h"
26
27 #include "smsc_widget.h"
28
29
30 int add_smsc_widget_page(struct smsc_widget *widget, int page_num)
31 {
32         struct smsc_page_data *page_data;
33         int posx;
34         int is_ok;
35         char img_fname[sizeof(PREVIEW_TEMP_DIR "/mobileprint_xxxx.ppm ")];
36
37         /*int w;
38         int h;
39         int x;
40         int y;*/
41
42         SMSC_TRACE_BEGIN;
43
44         SMSC_RETV_IF(NULL == widget, -1, "Invalid widget pointer");
45         SMSC_RETV_IF(page_num < 0
46                         || widget->engine.p_model.conf.pages_count <= 0
47                         || widget->engine.p_model.conf.pages_count <= page_num,
48                         -1, "Incorrect page number");
49
50         posx = get_smsc_position_page(&(widget->position), page_num, &is_ok);
51         SMSC_RETV_IF(!is_ok, -1, "Error in page position");
52
53         sprintf(img_fname, PREVIEW_TEMP_DIR "/mobileprint_%04d.ppm",
54                         page_num + 1);
55         page_data = (struct smsc_page_data*)
56                                 malloc(sizeof(struct smsc_page_data));
57         SMSC_RETV_IF(NULL == page_data, -1, "Memory allocation error");
58         page_data->num = page_num;
59
60         page_data->page_obj = evas_object_image_filled_add(widget->canvas);
61         if (widget->engine.p_model.pages_state[page_num + 1]
62                         == PREVIEW_PAGE_STATE_READY) {
63                 SMSC_DEBUG("loading image %s", img_fname);
64                 evas_object_image_file_set(
65                                 page_data->page_obj, img_fname, NULL);
66         } else {
67                 SMSC_DEBUG("page %d state: %d", page_num + 1,
68                                 widget->engine.p_model
69                                         .pages_state[page_num + 1]);
70                 evas_object_image_file_set(page_data->page_obj,
71                                 PREVIEW_EMPTY_PAGE_FNAME, NULL);
72         }
73         //evas_object_image_preload(page_data->page_obj, EINA_FALSE);
74         //evas_object_color_set(page_data->page_obj, 0, 0, 0, 255);
75
76         SMSC_DEBUG("posx = %d,"
77                         " widget->off_x = %d",
78                         posx, widget->off_x);
79         evas_object_move(page_data->page_obj,
80                         posx + widget->off_x, widget->posy);
81         evas_object_resize(page_data->page_obj,
82                         widget->position.page_size_px.x,
83                         widget->position.page_size_px.y);
84         evas_object_pass_events_set(page_data->page_obj, EINA_TRUE);
85         /* add object to smart object */
86         evas_object_smart_member_add(page_data->page_obj, widget->parent);
87         evas_object_show(page_data->page_obj);
88
89         widget->pages_list = eina_list_append(
90                         widget->pages_list, (void*)page_data);
91
92         SMSC_TRACE_END;
93         return 0;
94 }
95
96
97 int destroy_smsc_widget_page(struct smsc_page_data *page_data)
98 {
99         SMSC_TRACE_BEGIN;
100         SMSC_RETV_IF(NULL == page_data, -1, "Invalid page data pointer");
101
102         evas_object_hide(page_data->page_obj);
103         evas_object_del(page_data->page_obj);
104         free(page_data);
105
106         SMSC_TRACE_END;
107         return 0;
108 }
109
110
111 int destroy_smsc_widget_pages(struct smsc_widget *widget)
112 {
113         struct smsc_page_data* page_data;
114         SMSC_TRACE_BEGIN;
115         SMSC_RETV_IF(NULL == widget, -1, "Invalid widget pointer");
116         EINA_LIST_FREE(widget->pages_list, page_data)
117                 destroy_smsc_widget_page(page_data);
118         widget->pages_list = NULL;
119         SMSC_TRACE_END;
120
121         return 0;
122 }
123
124
125 int update_smsc_widget_page(struct smsc_widget *widget, int page_num)
126 {
127         Eina_List *cur_page = NULL;
128         char img_fname[sizeof(PREVIEW_TEMP_DIR "/mobileprint_xxxx.ppm ")];
129         struct smsc_page_data* page_data;
130
131         SMSC_TRACE_BEGIN;
132         SMSC_RETV_IF(NULL == widget, -1, "Invalid widget pointer");
133         SMSC_RETV_IF(page_num < 0
134                         || widget->engine.p_model.conf.pages_count <= 0
135                         || widget->engine.p_model.conf.pages_count <= page_num,
136                         -1, "Incorrect page number");
137
138         if (widget->engine.p_model.pages_state[page_num + 1]
139                         != PREVIEW_PAGE_STATE_READY)
140                 return -1;
141
142         sprintf(img_fname, PREVIEW_TEMP_DIR
143                         "/mobileprint_%04d.ppm", page_num + 1);
144         SMSC_DEBUG("page_num = %d", page_num);
145
146         EINA_LIST_FOREACH(widget->pages_list, cur_page, page_data)
147                 if (page_data->num == page_num)
148                         evas_object_image_file_set(
149                                         page_data->page_obj, img_fname, NULL);
150
151         SMSC_TRACE_END;
152         return 0;
153 }
154
155
156 int move_smsc_widget_pages(struct smsc_widget *widget)
157 {
158         int is_ok;
159         int posx;
160         Eina_List *cur_page = NULL;
161         struct smsc_page_data* page_data;
162
163         SMSC_RETV_IF(NULL == widget, -1, "Invalid widget pointer");
164         EINA_LIST_FOREACH(widget->pages_list, cur_page, page_data)
165                 if (page_data != NULL) {
166                         posx = get_smsc_position_page(&(widget->position),
167                                         page_data->num, &is_ok);
168                         if (is_ok)
169                                 evas_object_move(page_data->page_obj,
170                                                 posx + widget->off_x,
171                                                 widget->posy);
172                 }
173
174         return 0;
175 }
176
177
178 int update_smsc_widget_positions(struct smsc_widget *widget)
179 {
180         int *vis_pages;
181         int i;
182         Eina_List *old_pages_list = NULL;
183         Eina_List *cur_page = NULL;
184         int is_found;
185         int posx;
186         int is_ok;
187         struct smsc_page_data* page_data;
188
189         SMSC_TRACE_BEGIN;
190         SMSC_RETV_IF(NULL == widget, -1, "Invalid widget pointer");
191         //SMSC_DEBUG("update_smsc_widget_positions() started");
192
193         vis_pages = get_smsc_position_visible_pages(&(widget->position));
194         SMSC_RETV_IF(NULL == vis_pages, -1, "Invalid visible pages list");
195
196         /* construct new visible pages list */
197         old_pages_list = widget->pages_list;
198         widget->pages_list = NULL;
199         EINA_LIST_FREE(old_pages_list, page_data) {
200                 is_found = 0;
201                 if (page_data != NULL) {
202                         for (i = 0; vis_pages[i] >= 0; ++i) {
203                                 /*SMSC_DEBUG("update_smsc_widget_positions():"
204                                                 " i = %d, vis_pages[i] = %d", i,
205                                                 vis_pages[i]);*/
206                                 if (page_data->num == vis_pages[i]) {
207                                         is_found = 1;
208                                         /* move page to new list */
209                                         widget->pages_list = eina_list_append(
210                                                         widget->pages_list,
211                                                         page_data);
212                                         posx = get_smsc_position_page(
213                                                         &(widget->position),
214                                                         vis_pages[i], &is_ok);
215                                         /*SMSC_DEBUG("posx = %d,"
216                                                         " widget->off_x = %d",
217                                                         posx, widget->off_x);*/
218                                         if (is_ok)
219                                                 evas_object_move(
220                                                         page_data->page_obj,
221                                                         posx + widget->off_x,
222                                                         widget->posy);
223                                 }
224                         }
225                         if (!is_found)
226                                 destroy_smsc_widget_page(page_data);
227                 }
228         }
229
230         /* add new pages */
231         for (i = 0; vis_pages[i] >= 0; ++i) {
232                 is_found = 0;
233                 EINA_LIST_FOREACH(widget->pages_list, cur_page, page_data)
234                         if (page_data != NULL && page_data->num == vis_pages[i])
235                                 is_found = 1;
236                 if (!is_found) {
237                         /*SMSC_DEBUG("update_smsc_widget_positions(): adding,"
238                                         " i = %d, vis_pages[i] = %d",
239                                         i, vis_pages[i]);*/
240                         add_smsc_widget_page(widget, vis_pages[i]);
241                 }
242         }
243
244         free(vis_pages);
245
246         SMSC_TRACE_END;
247         return 0;
248 }
249
250
251 int hide_smsc_widget(struct smsc_widget *widget)
252 {
253         Eina_List *cur_page = NULL;
254         struct smsc_page_data* page_data;
255
256         SMSC_TRACE_BEGIN;
257         SMSC_RETV_IF(NULL == widget, -1, "Invalid widget pointer");
258
259         EINA_LIST_FOREACH(widget->pages_list, cur_page, page_data)
260                 if (page_data != NULL)
261                         evas_object_hide(page_data->page_obj);
262
263         SMSC_TRACE_END;
264         return 0;
265 }
266
267
268 int show_smsc_widget(struct smsc_widget *widget)
269 {
270         Eina_List *cur_page = NULL;
271         struct smsc_page_data* page_data;
272
273         SMSC_TRACE_BEGIN;
274         SMSC_RETV_IF(NULL == widget, -1, "Invalid widget pointer");
275
276         EINA_LIST_FOREACH(widget->pages_list, cur_page, page_data)
277                 if (page_data != NULL)
278                         evas_object_show(page_data->page_obj);
279
280         SMSC_TRACE_END;
281         return 0;
282 }
283
284
285 Evas_Object *loading_animation_add(Evas_Object *parent)
286 {
287         Evas_Object *res;
288         res = elm_progressbar_add(parent);
289         SMSC_RETV_IF(res == NULL, NULL, "res is NULL");
290
291         elm_object_style_set(res, "list_process");
292         evas_object_size_hint_align_set(res, EVAS_HINT_FILL, 0.5);
293         evas_object_size_hint_weight_set(res, EVAS_HINT_EXPAND,
294                         EVAS_HINT_EXPAND);
295         elm_progressbar_pulse(res, EINA_TRUE);
296         return res;
297 }
298
299
300 void show_smsc_widget_loading_animation(struct smsc_widget *widget)
301 {
302         SMSC_TRACE_BEGIN;
303         SMSC_RET_IF(NULL == widget || NULL == widget->loading_animation,
304                         "Invalid widget pointer");
305
306         evas_object_move(widget->loading_animation,
307                         widget->off_x, widget->off_y);
308         evas_object_resize(widget->loading_animation,
309                         widget->position.available_size.x,
310                         widget->position.available_size.y);
311         evas_object_raise(widget->loading_animation);
312         evas_object_show(widget->loading_animation);
313         SMSC_TRACE_END;
314 }
315
316
317 void hide_smsc_widget_loading_animation(struct smsc_widget *widget)
318 {
319         SMSC_TRACE_BEGIN;
320         SMSC_RET_IF(NULL == widget, "Invalid widget pointer");
321         if (NULL == widget->loading_animation)
322                 return;
323         evas_object_hide(widget->loading_animation);
324         SMSC_TRACE_END;
325 }
326
327
328 int update_smsc_widget_loading_animation(struct smsc_widget *widget)
329 {
330         int page_num;
331         SMSC_TRACE_BEGIN;
332         SMSC_RETV_IF(NULL == widget, -1, "Invalid widget pointer");
333         page_num = get_smsc_position_cur_page(&widget->position);
334         if (widget->engine.p_model.conf.pages_count <= 0) {
335                 show_smsc_widget_loading_animation(widget);
336                 SMSC_TRACE_END;
337                 return 0;
338         }
339         if (widget->engine.p_model.pages_state[page_num + 1]
340                         != PREVIEW_PAGE_STATE_READY)
341                 show_smsc_widget_loading_animation(widget);
342         else
343                 hide_smsc_widget_loading_animation(widget);
344         SMSC_TRACE_END;
345         return 0;
346 }
347
348
349 int smsc_widget_update_page_number(struct smsc_widget *widget)
350 {
351         int page_num;
352         char pages[16];
353
354         Evas *e;
355         int x;
356         int y;
357         int w;
358         int h;
359
360         SMSC_TRACE_BEGIN;
361         SMSC_RETV_IF(NULL == widget, -1, "Invalid widget pointer");
362
363         page_num = get_smsc_position_cur_page(&widget->position);
364         /* update page number */
365         if (widget->position.pages_count > 1) {
366                 snprintf(pages, 15, "%d / %d",
367                                 page_num + 1, widget->position.pages_count);
368                 pages[15] = '\0';
369         } else {
370                 strcpy(pages, " ");
371         }
372         edje_object_part_text_set(elm_layout_edje_get(widget->layout),
373                         "pagenumber", pages);
374
375         /* !!! hack to enforce text updating to avoid text image caching */
376         e = evas_object_evas_get(widget->layout);
377         evas_output_viewport_get(e, &x, &y, &w, &h);
378         /* enforce bottom updating */
379         evas_damage_rectangle_add(e, 0, h * 6 / 7, w, h / 7);
380
381         SMSC_TRACE_END;
382         return 0;
383 }
384
385
386 Eina_Bool smsc_widget_update_position(void *data, int type, void *event)
387 {
388         int *vis_pages;
389         int i;
390         struct smsc_widget *widget;
391         //int page_num;
392         //char pages[15];
393
394         SMSC_TRACE_BEGIN;
395         SMSC_RETV_IF(NULL == data || NULL == event,
396                         ECORE_CALLBACK_DONE, "Invalid pointer");
397
398         widget = (struct smsc_widget*)data;
399         /* update paper images positions */
400         update_smsc_widget_positions(widget);
401         smsc_widget_update_page_number(widget);
402         update_smsc_widget_loading_animation(widget);
403
404         //preview_model_debug_print_pages_state(&(widget->engine.p_model));
405
406         if (widget->engine.p_model.conf.pages_count <= 0)
407                 return ECORE_CALLBACK_DONE;
408
409         /* request engine for new pages */
410         vis_pages = get_smsc_position_visible_pages(&(widget->position));
411
412         if (NULL == vis_pages)
413                 return ECORE_CALLBACK_DONE;
414         for (i = 0; vis_pages[i] >= 0; ++i)
415                 if (widget->engine.p_model.pages_state[vis_pages[i] + 1]
416                                 == PREVIEW_PAGE_STATE_NA)
417                         preview_model_request_page(
418                                         &(widget->engine.p_model),
419                                         vis_pages[i] + 1);
420         free(vis_pages);
421         SMSC_TRACE_END;
422         return ECORE_CALLBACK_DONE;
423 }
424
425 void smsc_widget_mouse_up_cb(void *data, Evas *evas,
426                 Evas_Object *obj, void *event_info)
427 {
428         struct smsc_widget *widget = (struct smsc_widget*)data;
429         SMSC_TRACE_BEGIN;
430         SMSC_RET_IF(NULL == data || NULL == event_info, "Argument error");
431         Evas_Event_Mouse_Down *ev = event_info;
432         smsc_control_finish_move(&(widget->control), ev->canvas.x);
433         SMSC_TRACE_END;
434 }
435
436
437 void smsc_widget_mouse_down_cb(void *data, Evas *evas,
438                 Evas_Object *obj, void *event_info)
439 {
440         Evas_Event_Mouse_Down *ev = event_info;
441         struct smsc_widget *widget = (struct smsc_widget*)data;
442         SMSC_TRACE_BEGIN;
443
444         if (NULL == widget) {
445                 SMSC_TRACE_END;
446                 return;
447         }
448         /* send to smsc_control new coordinates and moving beginning */
449         smsc_control_begin_move(&(widget->control), ev->canvas.x);
450         SMSC_TRACE_END;
451 }
452
453
454 void smsc_widget_mouse_move_cb(void *data, Evas *evas,
455                 Evas_Object *obj, void *event_info)
456 {
457         Evas_Event_Mouse_Down *ev = event_info;
458         struct smsc_widget *widget = (struct smsc_widget*)data;
459         /* send to smsc_control new coordinates */
460         smsc_control_process_move(&(widget->control), ev->canvas.x);
461 }
462
463
464 int clear_smsc_widget(struct smsc_widget *widget)
465 {
466         SMSC_TRACE_BEGIN;
467         hide_smsc_widget_loading_animation(widget);
468         if (widget->pages_list != NULL)
469                 destroy_smsc_widget_pages(widget);
470         reset_smsc_control(&(widget->control));
471         clear_smsc_position_settings(&(widget->position));
472         smsc_widget_update_page_number(widget); /* clear page number */
473         //show_smsc_widget_loading_animation(widget);
474         SMSC_TRACE_END;
475         return 0;
476 }
477
478
479 int smsc_widget_load_near_pages(struct smsc_widget *widget, int page_num)
480 {
481         Eina_List *cur_page = NULL;
482         struct smsc_page_data* page_data;
483
484         if (widget->engine.p_model.conf.pages_count <= 0)
485                 return 0;
486
487         EINA_LIST_FOREACH(widget->pages_list, cur_page, page_data) {
488                 SMSC_DEBUG("page_data->num = %d", page_data->num);
489                 if (page_num == page_data->num) {
490                         if (page_num + 1 < widget->engine
491                                         .p_model.conf.pages_count
492                                         && PREVIEW_PAGE_STATE_NA
493                                         == widget->engine
494                                         .p_model.pages_state[page_num + 2])
495                                 preview_model_request_page(
496                                                 &(widget->engine.p_model),
497                                                 page_num + 1 + 1);
498                         if (page_num + 1 > 1
499                                         && PREVIEW_PAGE_STATE_NA
500                                         == widget->engine
501                                         .p_model.pages_state[page_num])
502                                 preview_model_request_page(
503                                                 &(widget->engine.p_model),
504                                                 page_num + 1 - 1);
505                 }
506         }
507
508         return 0;
509 }
510
511
512 int smsc_widget_calculate_posy(struct smsc_widget *widget, int page_h)
513 {
514         int h;
515         //int y;
516         int cy;
517
518         SMSC_TRACE_BEGIN;
519         SMSC_RETV_IF(NULL == widget || page_h <= 0, -1, "Incorrect arguments");
520
521         //evas_object_geometry_get(widget->parent, NULL, &y, NULL, &h);
522         h = widget->position.available_size.y;
523         if (h <= 0)
524                 return -1;
525
526         cy = widget->off_y + (h - page_h) / 2;
527
528         SMSC_DEBUG("cy = %d, off_y = %d, h = %d, page_h = %d",
529                         cy, widget->off_y, h, page_h);
530
531         return cy;
532 }
533
534
535 Eina_Bool smsc_widget_page_ready_cb(void *data, int type, void *event)
536 {
537         int pages_count;
538         struct smsc_widget *widget = (struct smsc_widget*)data;
539         struct preview_engine_event *event_data =
540                         (struct preview_engine_event*)event;
541
542         struct size_px *available_size_px;
543         struct size_pts page_size;
544         /*struct size_px shadow_size_px = {10, 10};
545         struct preview_page_req settings_req;*/
546         //struct preview_page_px settings_px;
547
548         SMSC_TRACE_BEGIN;
549
550         switch (event_data->status) {
551         case PREVIEW_ENGINE_EVENT_INITIAL_READY:
552                 /* initialization done: request for page */
553                 pages_count = widget->engine.p_model.conf.pages_count;
554                 if (pages_count <= 0)
555                         break;
556                 SMSC_DEBUG("PREVIEW_ENGINE_EVENT_INITIAL_READY,"
557                                 " pages_count = %d", pages_count);
558                 available_size_px = &(widget->engine.p_model.conf
559                                 .settings_req.available_size_px);
560
561                 page_size = widget->engine.p_model.conf.paper_size.s;
562                 if (widget->engine.p_model.conf.settings_req.is_rotate90)
563                         switch_size_pts_coords(&page_size);
564
565                 clear_smsc_widget(widget);
566                 set_smsc_position_settings(&(widget->position), pages_count,
567                                 available_size_px, &page_size);
568
569                 /* request empty page image */
570                 preview_model_request_empty_page(
571                                 &(widget->engine.p_model));
572                 //update_smsc_widget_loading_animation(widget);
573                 break;
574
575         case PREVIEW_ENGINE_EVENT_EMPTY_PAGE_READY:
576                 preview_model_request_page(&(widget->engine.p_model), 1);
577
578                 /* show empty pages */
579                 widget->posy = smsc_widget_calculate_posy(widget,
580                                 widget->position.page_size_px.y);
581
582                 smsc_widget_update_page_number(widget);
583                 update_smsc_widget_positions(widget);
584                 show_smsc_widget_loading_animation(widget);
585                 break;
586
587         case PREVIEW_ENGINE_EVENT_PAGE_READY:
588                 /* load page */
589                 SMSC_DEBUG("PREVIEW_ENGINE_EVENT_PAGE_READY,"
590                                 " event_data->page = %d", event_data->page);
591                 update_smsc_widget_page(widget, event_data->page - 1);
592                 update_smsc_widget_loading_animation(widget);
593                 smsc_widget_load_near_pages(widget, event_data->page - 1);
594                 break;
595
596         case PREVIEW_ENGINE_EVENT_PAGE_PROCESSING:
597                 /* TODO: show empty page */
598                 /*if (event_data->page == ugd->pt_files.current_index + 1) {
599                         show_loading_animation(ugd);
600                 }*/
601                 break;
602
603         case PREVIEW_ENGINE_EVENT_INITIAL_ERROR:
604         case PREVIEW_ENGINE_EVENT_PAGE_ERROR:
605                 /* TODO: something in error case */
606                 break;
607         }
608
609         SMSC_TRACE_END;
610         return ECORE_CALLBACK_DONE;
611 }
612
613
614 int smsc_widget_set_layout(struct smsc_widget *widget, Evas_Object *layout)
615 {
616         SMSC_TRACE_BEGIN;
617         SMSC_RETV_IF(NULL == widget || NULL == layout, -1,
618                         "Invalid arguments");
619
620         /* mouse events */
621         widget->layout = layout;
622         evas_object_event_callback_add(layout, EVAS_CALLBACK_MOUSE_DOWN,
623                         smsc_widget_mouse_down_cb, widget);
624         evas_object_event_callback_add(layout, EVAS_CALLBACK_MOUSE_UP,
625                         smsc_widget_mouse_up_cb, widget);
626         evas_object_event_callback_add(layout, EVAS_CALLBACK_MOUSE_MOVE,
627                         smsc_widget_mouse_move_cb, widget);
628
629         SMSC_TRACE_END;
630         return 0;
631 }
632
633
634 int init_smsc_widget(struct smsc_widget *widget,
635                 Evas_Object *parent)
636 {
637         SMSC_TRACE_BEGIN;
638
639         SMSC_RETV_IF(NULL == widget || NULL == parent, -1,
640                         "Invalid arguments");
641
642         memset(widget, 0, sizeof(struct smsc_widget));
643         widget->parent = parent;
644         widget->layout = NULL;
645         widget->canvas = evas_object_evas_get(parent);
646         widget->loading_animation = loading_animation_add(widget->parent);
647         evas_object_smart_member_add(widget->loading_animation, widget->parent);
648
649         show_smsc_widget_loading_animation(widget);
650         init_smsc_position(&(widget->position));
651         init_smsc_control(&(widget->control), &(widget->position));
652         init_preview_engine(&(widget->engine));
653
654         /* connect events */
655         /* position event */
656         ecore_event_handler_add(widget->position.position_update_event_type,
657                         smsc_widget_update_position, widget);
658
659         /* preview engine events */
660         ecore_event_handler_add(widget->engine.page_ready_event_type,
661                         smsc_widget_page_ready_cb, widget);
662
663         widget->is_ready = 1;
664
665         SMSC_TRACE_END;
666
667         return 0;
668 }
669
670
671 /* TODO: widget destruction */
672
673
674