d7ea1a2ced3f882047bea4c63cf86a1af2451f60
[platform/core/appfw/watchface-complication.git] / watchface-complication / watchface-editable.cc
1 /*
2  * Copyright (c) 2018 Samsung Electronics Co., Ltd.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #include <stdio.h>
18 #include <errno.h>
19 #include <glib.h>
20 #include <dlog.h>
21 #include <string>
22
23 #include "watchface-complication/include/watchface-editable.h"
24 #include "watchface-complication/include/watchface-editable-internal.h"
25 #include "watchface-complication/editables-container.hh"
26 #include "watchface-complication/design-element.hh"
27 #include "watchface-common/shared-handle.hh"
28 #include "watchface-complication/editables-manager.hh"
29 #include "watchface-common/watchface-util.hh"
30 #include "watchface-common/watchface-exception.hh"
31
32 #ifdef LOG_TAG
33 #undef LOG_TAG
34 #endif
35
36 #define LOG_TAG "WATCHFACE_COMPLICATION"
37
38 #define CANDIDATE_ID_KEY "__CANDIDATE_ID_KEY__"
39 #define CANDIDATE_NAME_KEY "__CANDIDATE_NAME_KEY__"
40 #define CANDIDATE_COLOR_R_KEY "__CANDIDATE_COLOR_R_KEY__"
41 #define CANDIDATE_COLOR_G_KEY "__CANDIDATE_COLOR_G_KEY__"
42 #define CANDIDATE_COLOR_B_KEY "__CANDIDATE_COLOR_B_KEY__"
43 #define CANDIDATE_COLOR_A_KEY "__CANDIDATE_COLOR_A_KEY__"
44 #define CANDIDATE_PREVIEW_IMAGE_KEY "__CANDIDATE_PREVIEW_IMAGE_KEY__"
45
46 using namespace std;
47 using namespace tizen_base;
48 using namespace watchface_complication;
49 struct complication_candidates_list_ {
50   GList* candidates_list;
51 };
52
53 struct editable_color_ {
54   int r;
55   int g;
56   int b;
57   int a;
58 };
59
60 class ReadyCallbackInfo {
61  public:
62   ReadyCallbackInfo(watchface_editable_edit_ready_cb cb, void* user_data)
63     : cb_(cb), user_data_(user_data) {
64   }
65
66   ReadyCallbackInfo(ReadyCallbackInfo&& b) noexcept {
67     cb_ = b.cb_;
68     user_data_ = b.user_data_;
69     b.cb_ = nullptr;
70     b.user_data_ = nullptr;
71   }
72
73   void Invoke(void* stub, const std::string& editor_appid) {
74     cb_(stub, editor_appid.c_str(), user_data_);
75   }
76
77   watchface_editable_edit_ready_cb GetCallback() {
78     return cb_;
79   }
80
81  private:
82   watchface_editable_edit_ready_cb cb_;
83   void* user_data_;
84 };
85
86 class UpdateCallbackInfo {
87  public:
88   UpdateCallbackInfo(watchface_editable_update_requested_cb cb, void* user_data)
89     : cb_(cb), user_data_(user_data) {
90   }
91
92   UpdateCallbackInfo(UpdateCallbackInfo&& b) noexcept {
93     cb_ = b.cb_;
94     user_data_ = b.user_data_;
95     b.cb_ = nullptr;
96     b.user_data_ = nullptr;
97   }
98
99   void Invoke(const void* handle, int selected_idx,
100       const watchface_editable_edit_state_e state) {
101     LOGI("call update");
102     cb_(const_cast<void*>(handle), selected_idx, state, user_data_);
103   }
104
105  private:
106   watchface_editable_update_requested_cb cb_;
107   void* user_data_;
108 };
109
110 class EditablesContainerStub : public EditablesContainer {
111  public:
112   EditablesContainerStub()
113     : EditablesContainer() {
114   }
115
116   void OnEditReady(const std::string& editor_id) override {
117     for (auto& i : ready_cb_list_) {
118       i->Invoke(static_cast<void*>(this), editor_id);
119     }
120     LOGI("On edit call!! ready !!");
121   }
122
123   void OnUpdate(shared_ptr<IEditable> ed, int selected_idx,
124                 IEditable::EditableState state) override {
125     SharedHandle<IEditable>* ptr = SharedHandle<IEditable>::Make(ed);
126     for (auto& i : update_cb_list_) {
127       i->Invoke(static_cast<const void*>(ptr), selected_idx,
128                 static_cast<const watchface_editable_edit_state_e>(state));
129     }
130     delete ptr;
131   }
132
133   int AddReadyCallbackInfo(unique_ptr<ReadyCallbackInfo> ci) {
134     for (auto& i : ready_cb_list_) {
135       if (i.get()->GetCallback() == ci->GetCallback()) {
136         LOGI("already registered callback");
137         return WATCHFACE_COMPLICATION_ERROR_INVALID_PARAMETER;
138       }
139     }
140
141     ready_cb_list_.emplace_back(move(ci));
142     return WATCHFACE_COMPLICATION_ERROR_NONE;
143   }
144
145   int RemoveReadyCallbackInfo(watchface_editable_edit_ready_cb ci) {
146     for (auto& i : ready_cb_list_) {
147       if (i.get()->GetCallback() == ci) {
148         ready_cb_list_.remove(i);
149         return WATCHFACE_COMPLICATION_ERROR_NONE;
150       }
151     }
152     return WATCHFACE_COMPLICATION_ERROR_INVALID_PARAMETER;
153   }
154
155   void ClearUpdateCallbackInfo() {
156     update_cb_list_.clear();
157   }
158
159   void AddUpdateCallbackInfo(unique_ptr<UpdateCallbackInfo> ci) {
160     update_cb_list_.emplace_back(move(ci));
161   }
162
163  private:
164   std::list<std::unique_ptr<ReadyCallbackInfo>> ready_cb_list_;
165   std::list<std::unique_ptr<UpdateCallbackInfo>> update_cb_list_;
166 };
167
168 static EditablesContainerStub* __container;
169
170 extern "C" EXPORT_API int watchface_editable_add_design_element(
171     watchface_editable_container_h handle, int edit_id, int cur_data_idx,
172     complication_candidates_list_h list_handle,
173     watchface_editable_highlight_h highlight, const char* editable_name) {
174   if (!watchface_complication::util::CheckWatchFeatureEnabled())
175     return WATCHFACE_COMPLICATION_ERROR_NOT_SUPPORTED;
176
177   if (handle == nullptr || list_handle == nullptr || editable_name == nullptr ||
178     list_handle->candidates_list == nullptr)
179     return WATCHFACE_COMPLICATION_ERROR_INVALID_PARAMETER;
180
181   if (cur_data_idx < 0 &&
182     cur_data_idx >= static_cast<int>(
183       g_list_length(list_handle->candidates_list)))
184     return WATCHFACE_COMPLICATION_ERROR_INVALID_PARAMETER;
185
186   EditablesContainerStub* ec = static_cast<EditablesContainerStub*>(handle);
187   GList* iter = list_handle->candidates_list;
188   std::list<std::shared_ptr<Bundle>> new_list;
189
190   for (; iter; iter = iter->next) {
191     bundle* data = reinterpret_cast<bundle*>(iter->data);
192     if (data == nullptr)
193       continue;
194
195     try {
196       new_list.emplace_back(new Bundle(data));
197     } catch (const std::exception& e) {
198       LOGE("Exception occurred : %s", e.what());
199       return WATCHFACE_COMPLICATION_ERROR_OUT_OF_MEMORY;
200     }
201   }
202
203   if (ec->IsExist(edit_id)) {
204     LOGE("ID already exist");
205     return WATCHFACE_COMPLICATION_ERROR_EXIST_ID;
206   }
207
208   try {
209     auto de = std::shared_ptr<IEditable>(
210       new DesignElement(edit_id, cur_data_idx));
211     if (highlight) {
212       /* Highlight should be copied */
213       IEditable::Highlight* high =
214           ((SharedHandle<IEditable::Highlight>*)highlight)->GetRawPtr();
215       de.get()->SetHighlight(
216           shared_ptr<IEditable::Highlight>(new IEditable::Highlight(*high)));
217     }
218
219     de.get()->SetLabel(std::string(editable_name));
220     int ret = de.get()->SetCandidates(new_list);
221     if (ret != WATCHFACE_COMPLICATION_ERROR_NONE)
222       return ret;
223
224     ec->Add(de, edit_id);
225   } catch (const std::bad_alloc &ba) {
226     LOGE("DesignElement::Exception bad_alloc");
227     return WATCHFACE_COMPLICATION_ERROR_OUT_OF_MEMORY;
228   }
229
230   return WATCHFACE_COMPLICATION_ERROR_NONE;
231 }
232
233 extern "C" EXPORT_API int watchface_editable_add_complication(
234     watchface_editable_container_h handle, int edit_id, complication_h comp,
235     watchface_editable_highlight_h highlight) {
236   if (!watchface_complication::util::CheckWatchFeatureEnabled())
237     return WATCHFACE_COMPLICATION_ERROR_NOT_SUPPORTED;
238
239   if (handle == nullptr || comp == nullptr)
240     return WATCHFACE_COMPLICATION_ERROR_INVALID_PARAMETER;
241
242   EditablesContainerStub* ec = static_cast<EditablesContainerStub*>(handle);
243   SharedHandle<IEditable>* sh = static_cast<SharedHandle<IEditable>*>(comp);
244   int ret;
245
246   /* Update candidates */
247   ret = SharedHandle<IEditable>::Share(sh).get()->SetCandidates(
248       std::list<std::shared_ptr<Bundle>>());
249
250   if (ret != WATCHFACE_COMPLICATION_ERROR_NONE)
251     return ret;
252
253   if (highlight) {
254     /* Highlight should be copied */
255     IEditable::Highlight* high =
256         ((SharedHandle<IEditable::Highlight>*)highlight)->GetRawPtr();
257     SharedHandle<IEditable>::Share(sh).get()->SetHighlight(
258         shared_ptr<IEditable::Highlight>(new IEditable::Highlight(*high)));
259   }
260
261   if (ec->IsExist(edit_id)) {
262     LOGE("ID already exist");
263     return WATCHFACE_COMPLICATION_ERROR_EXIST_ID;
264   }
265   ec->Add(SharedHandle<IEditable>::Share(sh), edit_id);
266   LOGI("Add comp %d", edit_id);
267
268   return WATCHFACE_COMPLICATION_ERROR_NONE;
269 }
270
271 extern "C" EXPORT_API int watchface_editable_request_edit(
272     watchface_editable_container_h handle,
273     watchface_editable_update_requested_cb cb, void* user_data) {
274   if (!watchface_complication::util::CheckWatchFeatureEnabled())
275     return WATCHFACE_COMPLICATION_ERROR_NOT_SUPPORTED;
276
277   if (handle == nullptr || cb == nullptr)
278     return WATCHFACE_COMPLICATION_ERROR_INVALID_PARAMETER;
279
280   static cynara_result pcr = COMPLICATION_CYNARA_UNKNOWN;
281   int ret = util::CheckPrivilege(PRIVILEGE_DATASHARING, &pcr);
282   if (ret != WATCHFACE_COMPLICATION_ERROR_NONE)
283     return ret;
284
285   EditablesContainerStub* ec = static_cast<EditablesContainerStub*>(handle);
286   unique_ptr<UpdateCallbackInfo> ci = unique_ptr<UpdateCallbackInfo>(
287       new (std::nothrow) UpdateCallbackInfo(cb, user_data));
288   if (ci.get() == nullptr) {
289     LOGE("Out of memory");
290     return WATCHFACE_COMPLICATION_ERROR_OUT_OF_MEMORY;
291   }
292   ec->ClearUpdateCallbackInfo();
293   ec->AddUpdateCallbackInfo(move(ci));
294   ret = ec->RequestEdit();
295
296   return ret;
297 }
298
299 extern "C" EXPORT_API int watchface_editable_add_edit_ready_cb(
300     watchface_editable_edit_ready_cb cb, void* user_data) {
301   if (!watchface_complication::util::CheckWatchFeatureEnabled())
302     return WATCHFACE_COMPLICATION_ERROR_NOT_SUPPORTED;
303
304   if (cb == nullptr)
305     return WATCHFACE_COMPLICATION_ERROR_INVALID_PARAMETER;
306
307   if (__container == nullptr) {
308     try {
309       __container = new EditablesContainerStub();
310     } catch (const std::exception& e) {
311       LOGE("Exception occurred : %s", e.what());
312       return WATCHFACE_COMPLICATION_ERROR_OUT_OF_MEMORY;
313     }
314   }
315   if (__container == nullptr) {
316     LOGE("Out of memory");
317     return WATCHFACE_COMPLICATION_ERROR_OUT_OF_MEMORY;
318   }
319
320   unique_ptr<ReadyCallbackInfo> ci = unique_ptr<ReadyCallbackInfo>(
321       new (std::nothrow) ReadyCallbackInfo(cb, user_data));
322   if (ci.get() == nullptr) {
323     LOGE("Out of memory");
324     return WATCHFACE_COMPLICATION_ERROR_OUT_OF_MEMORY;
325   }
326   int ret = __container->AddReadyCallbackInfo(move(ci));
327   if (ret != WATCHFACE_COMPLICATION_ERROR_NONE)
328     return ret;
329
330   return WATCHFACE_COMPLICATION_ERROR_NONE;
331 }
332
333 extern "C" EXPORT_API int watchface_editable_remove_edit_ready_cb(
334     watchface_editable_edit_ready_cb cb) {
335   if (!watchface_complication::util::CheckWatchFeatureEnabled())
336     return WATCHFACE_COMPLICATION_ERROR_NOT_SUPPORTED;
337
338   if (cb == nullptr || __container == nullptr)
339     return WATCHFACE_COMPLICATION_ERROR_INVALID_PARAMETER;
340
341   return __container->RemoveReadyCallbackInfo(cb);
342 }
343
344 extern "C" EXPORT_API int watchface_editable_get_current_data_idx(
345     const watchface_editable_h handle, int* idx) {
346   if (!watchface_complication::util::CheckWatchFeatureEnabled())
347     return WATCHFACE_COMPLICATION_ERROR_NOT_SUPPORTED;
348
349   if (handle == nullptr || idx == nullptr)
350     return WATCHFACE_COMPLICATION_ERROR_INVALID_PARAMETER;
351
352   SharedHandle<IEditable>* ie = static_cast<SharedHandle<IEditable>*>(handle);
353   *idx = ie->GetPtr()->GetCurDataIdx();
354   return WATCHFACE_COMPLICATION_ERROR_NONE;
355 }
356
357 extern "C" EXPORT_API int watchface_editable_get_current_data(
358     const watchface_editable_h handle, bundle** cur_data) {
359   if (!watchface_complication::util::CheckWatchFeatureEnabled())
360     return WATCHFACE_COMPLICATION_ERROR_NOT_SUPPORTED;
361
362   if (handle == nullptr || cur_data == nullptr)
363     return WATCHFACE_COMPLICATION_ERROR_INVALID_PARAMETER;
364
365   SharedHandle<IEditable>* ie = static_cast<SharedHandle<IEditable>*>(handle);
366   shared_ptr<Bundle> data = ie->GetPtr()->GetCurData();
367   if (data.get() == nullptr)
368     return WATCHFACE_COMPLICATION_ERROR_NO_DATA;
369   if (data->GetHandle() != nullptr) {
370     *cur_data = bundle_dup(data->GetHandle());
371     if (*cur_data == nullptr)
372       return WATCHFACE_COMPLICATION_ERROR_OUT_OF_MEMORY;
373   } else {
374     return WATCHFACE_COMPLICATION_ERROR_NO_DATA;
375   }
376   return WATCHFACE_COMPLICATION_ERROR_NONE;
377 }
378
379 extern "C" EXPORT_API int watchface_editable_get_nth_data(
380     const watchface_editable_h handle, int nth, bundle** nth_data) {
381   if (!watchface_complication::util::CheckWatchFeatureEnabled())
382     return WATCHFACE_COMPLICATION_ERROR_NOT_SUPPORTED;
383
384   if (handle == nullptr || nth_data == nullptr)
385     return WATCHFACE_COMPLICATION_ERROR_INVALID_PARAMETER;
386
387   SharedHandle<IEditable>* ie = static_cast<SharedHandle<IEditable>*>(handle);
388   shared_ptr<Bundle> data = ie->GetPtr()->GetNthData(nth);
389   if (data.get() == nullptr)
390     return WATCHFACE_COMPLICATION_ERROR_NO_DATA;
391   if (data->GetHandle() != nullptr) {
392     *nth_data = bundle_dup(data->GetHandle());
393     if (*nth_data == nullptr)
394       return WATCHFACE_COMPLICATION_ERROR_OUT_OF_MEMORY;
395   } else {
396     return WATCHFACE_COMPLICATION_ERROR_NO_DATA;
397   }
398   return WATCHFACE_COMPLICATION_ERROR_NONE;
399 }
400
401 extern "C" EXPORT_API int watchface_editable_get_editable_id(
402     const watchface_editable_h handle, int* editable_id) {
403   if (!watchface_complication::util::CheckWatchFeatureEnabled())
404     return WATCHFACE_COMPLICATION_ERROR_NOT_SUPPORTED;
405
406   if (handle == nullptr || editable_id == nullptr)
407     return WATCHFACE_COMPLICATION_ERROR_INVALID_PARAMETER;
408
409   SharedHandle<IEditable>* ie = static_cast<SharedHandle<IEditable>*>(handle);
410   *editable_id = ie->GetPtr()->GetEditableId();
411
412   return WATCHFACE_COMPLICATION_ERROR_NONE;
413 }
414
415 extern "C" EXPORT_API int watchface_editable_get_editable_name(
416     const watchface_editable_h handle, char** editable_name) {
417   if (!watchface_complication::util::CheckWatchFeatureEnabled())
418     return WATCHFACE_COMPLICATION_ERROR_NOT_SUPPORTED;
419
420   if (handle == nullptr || editable_name == nullptr)
421     return WATCHFACE_COMPLICATION_ERROR_INVALID_PARAMETER;
422
423   SharedHandle<IEditable>* ie = static_cast<SharedHandle<IEditable>*>(handle);
424   if (!ie->GetPtr()->GetLabel().empty()) {
425     *editable_name = strdup(ie->GetPtr()->GetLabel().c_str());
426     if (*editable_name == nullptr) {
427       LOGE("Out of memory");
428       return WATCHFACE_COMPLICATION_ERROR_OUT_OF_MEMORY;
429     }
430   } else {
431     return WATCHFACE_COMPLICATION_ERROR_NO_DATA;
432   }
433   return WATCHFACE_COMPLICATION_ERROR_NONE;
434 }
435
436 extern "C" EXPORT_API int watchface_editable_set_editable_name(
437     const watchface_editable_h handle, const char* editable_name) {
438   if (!watchface_complication::util::CheckWatchFeatureEnabled())
439     return WATCHFACE_COMPLICATION_ERROR_NOT_SUPPORTED;
440
441   if (handle == nullptr || editable_name == nullptr)
442     return WATCHFACE_COMPLICATION_ERROR_INVALID_PARAMETER;
443
444   SharedHandle<IEditable>* ie = static_cast<SharedHandle<IEditable>*>(handle);
445   ie->GetPtr()->SetLabel(std::string(editable_name));
446   return WATCHFACE_COMPLICATION_ERROR_NONE;
447 }
448
449 extern "C" EXPORT_API int watchface_editable_load_current_data(
450     int editable_id, bundle** selected_data) {
451   if (!watchface_complication::util::CheckWatchFeatureEnabled())
452     return WATCHFACE_COMPLICATION_ERROR_NOT_SUPPORTED;
453
454   if (selected_data == nullptr)
455     return WATCHFACE_COMPLICATION_ERROR_INVALID_PARAMETER;
456
457   std::unique_ptr<Bundle> setting_data;
458   try {
459     setting_data = EditablesManager::GetInst().LoadSetting(editable_id);
460   } catch (watchface_complication::Exception &ex) {
461     LOGE("%s %d", ex.what(), ex.GetErrorCode());
462     return ex.GetErrorCode();
463   }
464
465   if (setting_data != nullptr) {
466     bundle* dup_bundle = bundle_dup(setting_data.get()->GetHandle());
467     if (dup_bundle == nullptr)
468       return WATCHFACE_COMPLICATION_ERROR_OUT_OF_MEMORY;
469     *selected_data = dup_bundle;
470   } else {
471     return WATCHFACE_COMPLICATION_ERROR_NO_DATA;
472   }
473   return WATCHFACE_COMPLICATION_ERROR_NONE;
474 }
475
476 extern "C" EXPORT_API int watchface_editable_candidate_create(
477     bundle** candidate, const char* id) {
478   if (candidate == nullptr || id == nullptr) {
479     LOGE("Invalid parameter");
480     return WATCHFACE_COMPLICATION_ERROR_INVALID_PARAMETER;
481   }
482
483   bundle* data = bundle_create();
484   int ret = bundle_add_str(data, CANDIDATE_ID_KEY, id);
485   if (ret != BUNDLE_ERROR_NONE) {
486     LOGE("fail to add id (%d)", ret);
487     bundle_free(data);
488     return WATCHFACE_COMPLICATION_ERROR_IO_ERROR;
489   }
490   *candidate = data;
491
492   return WATCHFACE_COMPLICATION_ERROR_NONE;
493 }
494
495 extern "C" EXPORT_API int watchface_editable_candidate_get_id(
496     bundle* candidate, char** id) {
497   if (candidate == nullptr || id == nullptr) {
498     LOGE("Invalid parameter");
499     return WATCHFACE_COMPLICATION_ERROR_INVALID_PARAMETER;
500   }
501
502   char* data;
503   int ret = bundle_get_str(candidate, CANDIDATE_ID_KEY, &data);
504   if (ret != BUNDLE_ERROR_NONE) {
505     LOGW("No data");
506     return WATCHFACE_COMPLICATION_ERROR_NO_DATA;
507   }
508   *id = strdup(data);
509
510   return WATCHFACE_COMPLICATION_ERROR_NONE;
511 }
512
513 extern "C" EXPORT_API int watchface_editable_candidate_set_name(
514     bundle* candidate, const char* name) {
515   if (candidate == nullptr || name == nullptr) {
516     LOGE("Invalid parameter");
517     return WATCHFACE_COMPLICATION_ERROR_INVALID_PARAMETER;
518   }
519
520   int ret = bundle_add_str(candidate, CANDIDATE_NAME_KEY, name);
521   if (ret != BUNDLE_ERROR_NONE) {
522     LOGE("fail to add name (%d)", ret);
523     return WATCHFACE_COMPLICATION_ERROR_IO_ERROR;
524   }
525   return WATCHFACE_COMPLICATION_ERROR_NONE;
526 }
527
528 extern "C" EXPORT_API int watchface_editable_candidate_get_name(
529     bundle* candidate, char** name) {
530   if (candidate == nullptr || name == nullptr) {
531     LOGE("Invalid parameter");
532     return WATCHFACE_COMPLICATION_ERROR_INVALID_PARAMETER;
533   }
534
535   char* data;
536   int ret = bundle_get_str(candidate, CANDIDATE_NAME_KEY, &data);
537   if (ret != BUNDLE_ERROR_NONE) {
538     LOGW("No data");
539     return WATCHFACE_COMPLICATION_ERROR_NO_DATA;
540   }
541   *name = strdup(data);
542
543   return WATCHFACE_COMPLICATION_ERROR_NONE;
544 }
545
546 extern "C" EXPORT_API int watchface_editable_candidate_set_color(
547     bundle* candidate, watchface_editable_color_h color) {
548   if (candidate == nullptr) {
549     LOGE("Invalid parameter");
550     return WATCHFACE_COMPLICATION_ERROR_INVALID_PARAMETER;
551   }
552
553   bundle_del(candidate, CANDIDATE_COLOR_A_KEY);
554   bundle_del(candidate, CANDIDATE_COLOR_R_KEY);
555   bundle_del(candidate, CANDIDATE_COLOR_G_KEY);
556   bundle_del(candidate, CANDIDATE_COLOR_B_KEY);
557   if (color != nullptr) {
558     bundle_add_str(candidate, CANDIDATE_COLOR_A_KEY, to_string(color->a).c_str());
559     bundle_add_str(candidate, CANDIDATE_COLOR_R_KEY, to_string(color->r).c_str());
560     bundle_add_str(candidate, CANDIDATE_COLOR_G_KEY, to_string(color->g).c_str());
561     bundle_add_str(candidate, CANDIDATE_COLOR_B_KEY, to_string(color->b).c_str());
562   }
563   return WATCHFACE_COMPLICATION_ERROR_NONE;
564 }
565
566 extern "C" EXPORT_API int watchface_editable_candidate_get_color(
567     bundle* candidate, watchface_editable_color_h* color) {
568   if (candidate == nullptr || color == nullptr) {
569     LOGE("Invalid parameter");
570     return WATCHFACE_COMPLICATION_ERROR_INVALID_PARAMETER;
571   }
572
573   char* r_str = nullptr;
574   char* g_str = nullptr;
575   char* b_str = nullptr;
576   char* a_str = nullptr;
577
578   bundle_get_str(candidate, CANDIDATE_COLOR_A_KEY, &a_str);
579   bundle_get_str(candidate, CANDIDATE_COLOR_R_KEY, &r_str);
580   bundle_get_str(candidate, CANDIDATE_COLOR_G_KEY, &g_str);
581   bundle_get_str(candidate, CANDIDATE_COLOR_B_KEY, &b_str);
582
583   watchface_editable_color_h col;
584   if (r_str != nullptr) {
585     int ret = watchface_editable_candidate_color_create(&col,
586         stoi(r_str), stoi(g_str), stoi(b_str), stoi(a_str));
587     if (ret != WATCHFACE_COMPLICATION_ERROR_NONE)
588       return ret;
589     *color = col;
590   } else {
591     LOGW("No data");
592     return WATCHFACE_COMPLICATION_ERROR_NO_DATA;
593   }
594
595   return WATCHFACE_COMPLICATION_ERROR_NONE;
596 }
597
598 extern "C" EXPORT_API int watchface_editable_candidate_color_create(
599     watchface_editable_color_h* color, int r, int g, int b, int a) {
600
601   if (color == nullptr || r < 0 || r > 255
602        || g < 0 || g > 255 || b < 0 || b > 255 || a < 0 || a > 255) {
603     LOGE("Invalid parameter");
604     return WATCHFACE_COMPLICATION_ERROR_INVALID_PARAMETER;
605   }
606   watchface_editable_color_h col =
607       (watchface_editable_color_h)calloc(1, sizeof(struct editable_color_));
608   col->r = r;
609   col->g = g;
610   col->b = b;
611   col->a = a;
612   *color = col;
613
614   return WATCHFACE_COMPLICATION_ERROR_NONE;
615 }
616
617 extern "C" EXPORT_API int watchface_editable_candidate_color_get(
618       watchface_editable_color_h color, int* r, int* g, int* b, int* a) {
619   if (color == nullptr
620       || r == nullptr || g == nullptr || b == nullptr || a == nullptr) {
621     LOGE("Invalid parameter");
622     return WATCHFACE_COMPLICATION_ERROR_INVALID_PARAMETER;
623   }
624
625   *r = color->r;
626   *g = color->g;
627   *b = color->b;
628   *a = color->a;
629
630   return WATCHFACE_COMPLICATION_ERROR_NONE;
631 }
632
633 extern "C" EXPORT_API int watchface_editable_candidate_color_destroy(
634       watchface_editable_color_h color) {
635   if (color == nullptr) {
636     LOGE("Invalid parameter");
637     return WATCHFACE_COMPLICATION_ERROR_INVALID_PARAMETER;
638   }
639   free(color);
640   return WATCHFACE_COMPLICATION_ERROR_NONE;
641 }
642
643 extern "C" EXPORT_API int watchface_editable_candidate_set_preview_image(
644       bundle *candidate, const char *path) {
645   if (candidate == nullptr || path == nullptr) {
646     LOGE("Invalid parameter");
647     return WATCHFACE_COMPLICATION_ERROR_INVALID_PARAMETER;
648   }
649
650   bundle_del(candidate, CANDIDATE_PREVIEW_IMAGE_KEY);
651   int ret = bundle_add_str(candidate, CANDIDATE_PREVIEW_IMAGE_KEY, path);
652   if (ret != BUNDLE_ERROR_NONE) {
653     LOGE("fail to add path");
654     return WATCHFACE_COMPLICATION_ERROR_IO_ERROR;
655   }
656
657   return WATCHFACE_COMPLICATION_ERROR_NONE;
658 }
659
660 extern "C" EXPORT_API int watchface_editable_candidate_get_preview_image(
661       bundle* candidate, char** path) {
662   if (candidate == nullptr || path == nullptr) {
663     LOGE("Invalid parameter");
664     return WATCHFACE_COMPLICATION_ERROR_INVALID_PARAMETER;
665   }
666
667   char* image;
668   int ret = bundle_get_str(candidate, CANDIDATE_PREVIEW_IMAGE_KEY, &image);
669   if (ret != BUNDLE_ERROR_NONE) {
670     LOGW("No data");
671     return WATCHFACE_COMPLICATION_ERROR_NO_DATA;
672   }
673   *path = strdup(image);
674
675   return WATCHFACE_COMPLICATION_ERROR_NONE;
676 }
677
678 extern "C" EXPORT_API int watchface_editable_candidates_list_create(
679     complication_candidates_list_h* handle) {
680   complication_candidates_list_h h = nullptr;
681
682   if (!watchface_complication::util::CheckWatchFeatureEnabled())
683     return WATCHFACE_COMPLICATION_ERROR_NOT_SUPPORTED;
684
685   if (handle == nullptr) {
686     LOGE("Invalid param");
687     return WATCHFACE_COMPLICATION_ERROR_INVALID_PARAMETER;
688   }
689
690   h = (complication_candidates_list_h)calloc(1,
691       sizeof(struct complication_candidates_list_));
692
693   if (h == nullptr) {
694     LOGE("Out of memory");
695     return WATCHFACE_COMPLICATION_ERROR_OUT_OF_MEMORY;
696   }
697
698   *handle = h;
699
700   return WATCHFACE_COMPLICATION_ERROR_NONE;
701 }
702
703 extern "C" EXPORT_API int watchface_editable_candidates_list_add(
704     complication_candidates_list_h handle, bundle* candidate) {
705   if (!watchface_complication::util::CheckWatchFeatureEnabled())
706     return WATCHFACE_COMPLICATION_ERROR_NOT_SUPPORTED;
707
708   if (handle == nullptr || candidate == nullptr) {
709     LOGE("Invalid param");
710     return WATCHFACE_COMPLICATION_ERROR_INVALID_PARAMETER;
711   }
712
713   bundle* dup_candidate = bundle_dup(candidate);
714   if (dup_candidate == nullptr) {
715     LOGE("Out of memory");
716     return WATCHFACE_COMPLICATION_ERROR_OUT_OF_MEMORY;
717   }
718   handle->candidates_list = g_list_append(
719       handle->candidates_list, dup_candidate);
720
721   return WATCHFACE_COMPLICATION_ERROR_NONE;
722 }
723
724 static void __free_candidate(gpointer data) {
725   bundle* candidate = reinterpret_cast<bundle*>(data);
726   bundle_free(candidate);
727 }
728
729 extern "C" EXPORT_API int watchface_editable_candidates_list_destroy(
730     complication_candidates_list_h handle) {
731   if (!watchface_complication::util::CheckWatchFeatureEnabled())
732     return WATCHFACE_COMPLICATION_ERROR_NOT_SUPPORTED;
733
734   if (handle == nullptr) {
735     LOGE("Invalid param");
736     return WATCHFACE_COMPLICATION_ERROR_INVALID_PARAMETER;
737   }
738
739   if (handle->candidates_list)
740     g_list_free_full(handle->candidates_list, __free_candidate);
741   free(handle);
742
743   return WATCHFACE_COMPLICATION_ERROR_NONE;
744 }
745
746 extern "C" EXPORT_API int watchface_editable_container_get(
747     watchface_editable_container_h* container) {
748   if (!watchface_complication::util::CheckWatchFeatureEnabled())
749     return WATCHFACE_COMPLICATION_ERROR_NOT_SUPPORTED;
750
751   if (container == nullptr) {
752     LOGE("Invalid param");
753     return WATCHFACE_COMPLICATION_ERROR_INVALID_PARAMETER;
754   }
755
756   if (__container == nullptr) {
757     LOGE("Container is not ready yet");
758     return WATCHFACE_COMPLICATION_ERROR_IO_ERROR;
759   }
760
761   *container = __container;
762
763   return WATCHFACE_COMPLICATION_ERROR_NONE;
764 }
765
766 extern "C" EXPORT_API int watchface_editable_highlight_create(
767     watchface_editable_highlight_h* handle,
768     watchface_editable_shape_type_e shape) {
769   watchface_editable_highlight_h h = nullptr;
770
771   if (!watchface_complication::util::CheckWatchFeatureEnabled())
772     return WATCHFACE_COMPLICATION_ERROR_NOT_SUPPORTED;
773
774   if (handle == nullptr || shape < WATCHFACE_EDITABLE_SHAPE_TYPE_CIRCLE ||
775       WATCHFACE_EDITABLE_SHAPE_TYPE_RECT < shape) {
776     LOGE("Invalid param");
777     return WATCHFACE_COMPLICATION_ERROR_INVALID_PARAMETER;
778   }
779
780   h = (watchface_editable_highlight_h)SharedHandle<IEditable::Highlight>::Make(
781     make_shared<IEditable::Highlight>((IEditable::EditableShapeType)shape)
782   );
783   *handle = h;
784
785   return WATCHFACE_COMPLICATION_ERROR_NONE;
786 }
787
788 extern "C" EXPORT_API int watchface_editable_highlight_set_normalized_geometry(
789     watchface_editable_highlight_h handle, double x, double y, double w, double h) {
790
791   if (!watchface_complication::util::CheckWatchFeatureEnabled())
792     return WATCHFACE_COMPLICATION_ERROR_NOT_SUPPORTED;
793
794   if (handle == nullptr || x < 0.0 || y < 0.0 || w < 0.0 || h < 0.0  ||
795       x > 1.0 || y > 1.0 || w > 1.0 || h > 1.0) {
796     LOGE("Invalid param");
797     return WATCHFACE_COMPLICATION_ERROR_INVALID_PARAMETER;
798   }
799
800   shared_ptr<IEditable::Highlight> ptr =
801       ((SharedHandle<IEditable::Highlight>*)handle)->GetPtr();
802   ptr->SetNormalizedGeometry(
803       unique_ptr<IEditable::NormalizedGeometry>(
804         new IEditable::NormalizedGeometry(x, y, w, h)));
805
806   return WATCHFACE_COMPLICATION_ERROR_NONE;
807 }
808
809 extern "C" EXPORT_API int watchface_editable_highlight_get_normalized_geometry(
810     watchface_editable_highlight_h handle, double *x, double *y, double *w, double *h) {
811   if (!watchface_complication::util::CheckWatchFeatureEnabled())
812     return WATCHFACE_COMPLICATION_ERROR_NOT_SUPPORTED;
813
814   if (handle == nullptr || x == nullptr || y == nullptr || w == nullptr || h == nullptr) {
815     LOGE("Invalid param");
816     return WATCHFACE_COMPLICATION_ERROR_INVALID_PARAMETER;
817   }
818
819   shared_ptr<IEditable::Highlight> ptr =
820       ((SharedHandle<IEditable::Highlight>*)handle)->GetPtr();
821   *x = ptr->GetNormalizedGeometry()->GetNormalizedX();
822   *y = ptr->GetNormalizedGeometry()->GetNormalizedY();
823   *w = ptr->GetNormalizedGeometry()->GetNormalizedW();
824   *h = ptr->GetNormalizedGeometry()->GetNormalizedH();
825
826   return WATCHFACE_COMPLICATION_ERROR_NONE;
827 }
828
829 extern "C" EXPORT_API int watchface_editable_highlight_set_geometry(
830     watchface_editable_highlight_h handle, int x, int y, int w, int h) {
831   if (!watchface_complication::util::CheckWatchFeatureEnabled())
832     return WATCHFACE_COMPLICATION_ERROR_NOT_SUPPORTED;
833
834   if (handle == nullptr || x < 0 || y < 0 || w < 0 || h < 0) {
835     LOGE("Invalid param");
836     return WATCHFACE_COMPLICATION_ERROR_INVALID_PARAMETER;
837   }
838
839   shared_ptr<IEditable::Highlight> ptr =
840       ((SharedHandle<IEditable::Highlight>*)handle)->GetPtr();
841   IEditable::Geometry geo(x, y, w, h);
842   ptr->SetGeometry(geo);
843
844   return WATCHFACE_COMPLICATION_ERROR_NONE;
845 }
846
847 extern "C" EXPORT_API int watchface_editable_highlight_get_geometry(
848     watchface_editable_highlight_h handle, int* x, int* y, int* w, int* h) {
849   if (!watchface_complication::util::CheckWatchFeatureEnabled())
850     return WATCHFACE_COMPLICATION_ERROR_NOT_SUPPORTED;
851
852   if (handle == nullptr || x == nullptr || y == nullptr || w == nullptr || h == nullptr) {
853     LOGE("Invalid param");
854     return WATCHFACE_COMPLICATION_ERROR_INVALID_PARAMETER;
855   }
856
857   shared_ptr<IEditable::Highlight> ptr =
858       ((SharedHandle<IEditable::Highlight>*)handle)->GetPtr();
859   *x = ptr->GetGeometry()->GetX();
860   *y = ptr->GetGeometry()->GetY();
861   *w = ptr->GetGeometry()->GetW();
862   *h = ptr->GetGeometry()->GetH();
863
864   return WATCHFACE_COMPLICATION_ERROR_NONE;
865 }
866
867 extern "C" EXPORT_API int watchface_editable_highlight_set_shape_type(
868     watchface_editable_highlight_h handle,
869     watchface_editable_shape_type_e shape) {
870   if (!watchface_complication::util::CheckWatchFeatureEnabled())
871     return WATCHFACE_COMPLICATION_ERROR_NOT_SUPPORTED;
872
873   if (handle == nullptr
874         || shape < WATCHFACE_EDITABLE_SHAPE_TYPE_CIRCLE
875         || shape > WATCHFACE_EDITABLE_SHAPE_TYPE_RECT) {
876     LOGE("Invalid param");
877     return WATCHFACE_COMPLICATION_ERROR_INVALID_PARAMETER;
878   }
879   shared_ptr<IEditable::Highlight> ptr =
880       ((SharedHandle<IEditable::Highlight>*)handle)->GetPtr();
881   ptr->SetShapeType((IEditable::EditableShapeType)shape);
882
883   return WATCHFACE_COMPLICATION_ERROR_NONE;
884 }
885
886 extern "C" EXPORT_API int watchface_editable_highlight_get_shape_type(
887     watchface_editable_highlight_h handle,
888     watchface_editable_shape_type_e* shape) {
889   if (!watchface_complication::util::CheckWatchFeatureEnabled())
890     return WATCHFACE_COMPLICATION_ERROR_NOT_SUPPORTED;
891
892   if (handle == nullptr || shape == nullptr) {
893     LOGE("Invalid param");
894     return WATCHFACE_COMPLICATION_ERROR_INVALID_PARAMETER;
895   }
896   shared_ptr<IEditable::Highlight> ptr =
897       ((SharedHandle<IEditable::Highlight>*)handle)->GetPtr();
898   *shape = (watchface_editable_shape_type_e)ptr->GetShapeType();
899
900   return WATCHFACE_COMPLICATION_ERROR_NONE;
901 }
902
903 extern "C" EXPORT_API int watchface_editable_highlight_destroy(
904     watchface_editable_highlight_h handle) {
905   if (!watchface_complication::util::CheckWatchFeatureEnabled())
906     return WATCHFACE_COMPLICATION_ERROR_NOT_SUPPORTED;
907
908   if (handle == nullptr) {
909     LOGE("Invalid param");
910     return WATCHFACE_COMPLICATION_ERROR_INVALID_PARAMETER;
911   }
912   free(handle);
913
914   return WATCHFACE_COMPLICATION_ERROR_NONE;
915 }
916
917 extern "C" EXPORT_API int watchface_editable_get_highlight(
918     const watchface_editable_h handle,
919     watchface_editable_highlight_h* highlight) {
920   if (!watchface_complication::util::CheckWatchFeatureEnabled())
921     return WATCHFACE_COMPLICATION_ERROR_NOT_SUPPORTED;
922
923   if (handle == nullptr || highlight == nullptr) {
924     LOGE("Invalid param");
925     return WATCHFACE_COMPLICATION_ERROR_INVALID_PARAMETER;
926   }
927
928   SharedHandle<IEditable>* ie = static_cast<SharedHandle<IEditable>*>(handle);
929   shared_ptr<IEditable::Highlight> info = ie->GetPtr()->GetHighlight();
930   if (info == nullptr) {
931     LOGE("editor do not have highlight data");
932     return WATCHFACE_COMPLICATION_ERROR_NO_DATA;
933   }
934
935   *highlight = SharedHandle<IEditable::Highlight>::Make(info);
936
937   return WATCHFACE_COMPLICATION_ERROR_NONE;
938 }
939
940 extern "C" EXPORT_API int watchface_editable_edit_done(
941     watchface_editable_h handle) {
942   if (!watchface_complication::util::CheckWatchFeatureEnabled())
943     return WATCHFACE_COMPLICATION_ERROR_NOT_SUPPORTED;
944
945   if (handle == nullptr) {
946     LOGE("Invalid param");
947     return WATCHFACE_COMPLICATION_ERROR_INVALID_PARAMETER;
948   }
949
950   SharedHandle<IEditable>* ie = static_cast<SharedHandle<IEditable>*>(handle);
951   shared_ptr<IEditable> ptr = ie->GetPtr();
952   if (!__container->SendEditResult(
953           ptr->GetEditableId(), ptr->GetEditSequence(),
954           WATCHFACE_COMPLICATION_ERROR_NONE)) {
955     LOGE("Fail to send edit result");
956     return WATCHFACE_COMPLICATION_ERROR_IO_ERROR;
957   }
958
959   return WATCHFACE_COMPLICATION_ERROR_NONE;
960 }
961
962 extern "C" EXPORT_API int watchface_editable_dup(
963     const watchface_editable_h handle, watchface_editable_h *dup_handle) {
964   if (!watchface_complication::util::CheckWatchFeatureEnabled())
965     return WATCHFACE_COMPLICATION_ERROR_NOT_SUPPORTED;
966
967   if (handle == nullptr || dup_handle == nullptr) {
968     LOGE("Invalid param");
969     return WATCHFACE_COMPLICATION_ERROR_INVALID_PARAMETER;
970   }
971   SharedHandle<IEditable>* ie = static_cast<SharedHandle<IEditable>*>(handle);
972   *dup_handle = SharedHandle<IEditable>::Make(ie->GetPtr());
973   return WATCHFACE_COMPLICATION_ERROR_NONE;
974 }
975
976 extern "C" EXPORT_API int watchface_editable_destroy(watchface_editable_h handle) {
977   if (!watchface_complication::util::CheckWatchFeatureEnabled())
978     return WATCHFACE_COMPLICATION_ERROR_NOT_SUPPORTED;
979
980   if (handle == nullptr) {
981     LOGE("Invalid param");
982     return WATCHFACE_COMPLICATION_ERROR_INVALID_PARAMETER;
983   }
984   SharedHandle<IEditable>* ie = static_cast<SharedHandle<IEditable>*>(handle);
985   delete ie;
986   return WATCHFACE_COMPLICATION_ERROR_NONE;
987 }
988
989