summaryrefslogtreecommitdiff
path: root/src/memo_text_editor.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/memo_text_editor.c')
-rw-r--r--src/memo_text_editor.c420
1 files changed, 420 insertions, 0 deletions
diff --git a/src/memo_text_editor.c b/src/memo_text_editor.c
new file mode 100644
index 0000000..68e9b10
--- /dev/null
+++ b/src/memo_text_editor.c
@@ -0,0 +1,420 @@
+/*
+*
+* Copyright 2012 Samsung Electronics Co., Ltd
+*
+* Licensed under the Flora License, Version 1.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://floralicense.org/license/
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*
+*/
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <appcore-efl.h>
+#include <Elementary.h>
+#include <dlog.h>
+#include <gravel.h>
+#include <vconf-keys.h>
+#include <extended-elm.h>
+#include <supplement.h>
+#include <memo-assist.h>
+#include <memo_string.h>
+
+typedef struct __text_editor_t {
+ Evas_Object *win;
+ Evas_Object *parent;
+ Memo_Component_Callback cb;
+ void *data;
+ memo_data_t *record;
+ char buf[MEMO_BUFFER_SIZE]; /* for temporarily usage only */
+ Eina_Bool savable;
+
+ /* content */
+ Evas_Object *body_main;
+ Evas_Object *toolbar;
+ Evas_Object *btn_size;
+ void *h_fss;
+ Evas_Object *btn_color;
+ void *h_fcs;
+
+ /* entry */
+ Evas_Object *entry;
+ Ecore_IMF_Context *imf_context;
+ Elm_Entry_Filter_Limit_Size limit_filter_data;
+
+ /* original font information */
+ int init_fsize;
+ int init_fcolor;
+} text_editor_t;
+
+static void _font_size_selector_del(text_editor_t *te);
+static void _font_color_selector_del(text_editor_t *te);
+service_h text_service = NULL;
+static void _save_record(text_editor_t *te)
+{
+ if (te->record->content != NULL) {
+ SFREE(te->record->content);
+ }
+
+ /* content will be freed automatically in memo_free_data when editor destoried */
+ te->record->content = elm_entry_markup_to_utf8(elm_entry_entry_get(te->entry));
+ /* records synced from KIES has no font info, apply font enforce policy here to overwrite default font info */
+ te->record->font_respect = 1;
+ if (te->record->id != -1) {
+ memo_mod_data(te->record);
+ } else {
+ memo_add_data(te->record);
+ }
+}
+
+static void _on_save_yes(void *data, Evas_Object *obj, void *event_info)
+{
+ text_editor_t *te = (text_editor_t *)data;
+ _save_record(te);
+ te->cb(te->data, "save", NULL);
+}
+
+static void _on_save_no(void *data, Evas_Object *obj, void *event_info)
+{
+ text_editor_t *te = (text_editor_t *)data;
+ te->cb(te->data, "cancel", NULL);
+}
+
+static Eina_Bool _launch_yes_no_popup(void *data)
+{
+ text_editor_t *te = (text_editor_t *)data;
+ memo_create_yes_no_popup(te->win, MEMO_I18N_SAVE_MEMO, _on_save_yes, _on_save_no, te);
+ return EINA_FALSE;
+}
+
+static void _entry_content_update(text_editor_t *te)
+{
+ unsigned char *color = (unsigned char *)&te->record->font_color;
+ char *content = elm_entry_markup_to_utf8(elm_entry_entry_get(te->entry));
+ char *markup = elm_entry_utf8_to_markup(content);
+ snprintf(te->buf, MEMO_BUFFER_SIZE,
+ "<font_size=%d><color=#%02x%02x%02x>", te->record->font_size, color[2], color[1],
+ color[0]);
+ elm_entry_entry_set(te->entry, te->buf);
+ elm_entry_entry_insert(te->entry, markup);
+ SFREE(content);
+ SFREE(markup);
+}
+
+static void _font_size_selector_callback(void *data, const char *msg, void *event)
+{
+ text_editor_t *te = (text_editor_t *)data;
+ if (strcmp(msg, "layout") == 0) {
+ elm_object_part_content_set(te->body_main, "elm.swallow.tool", (Evas_Object *)event);
+ } else if (strcmp(msg, "change") == 0) {
+ te->record->font_size = (int)event;
+ _entry_content_update(te);
+ } else if (strcmp(msg, "flick,down") == 0) {
+ _font_size_selector_del(te);
+ edje_object_signal_emit(elm_layout_edje_get(te->body_main), "expand", "elm");
+ }
+}
+
+static void _font_size_selector_del(text_editor_t *te)
+{
+ if (te->h_fss != NULL) {
+ elm_object_part_content_unset(te->body_main, "elm.swallow.tool");
+ memo_del_font_size_selector(te->h_fss);
+ te->h_fss = NULL;
+ memo_tool_btn_focus_set(te->btn_size, EINA_FALSE);
+ }
+}
+
+static void _on_font_size_btn_up(void *data, Evas *e, Evas_Object *evas_obj, void *event_info)
+{
+ text_editor_t *te = (text_editor_t *)data;
+ if (te->h_fss != NULL) { /* font size selector already open */
+ return;
+ }
+ if (te->h_fcs != NULL) { /* destroy font color selector */
+ _font_color_selector_del(te);
+ }
+ /* load font size selector */
+ service_h service = NULL;
+ service_create(&service);
+ snprintf(te->buf, MEMO_BUFFER_SIZE, "%d", te->record->font_size);
+ service_add_extra_data(service, "current", te->buf);
+ snprintf(te->buf, MEMO_BUFFER_SIZE, "%d", 0xFFFFFFFF);
+ service_add_extra_data(service, "bg_color", te->buf);
+ te->h_fss = memo_load_font_size_selector(te->body_main, service, _font_size_selector_callback, te);
+ service_destroy(service);
+ memo_tool_btn_focus_set(te->btn_size, EINA_TRUE);
+ edje_object_signal_emit(elm_layout_edje_get(te->body_main), "abbrev", "elm");
+ /* hide input panel */
+ ecore_imf_context_input_panel_hide(te->imf_context);
+}
+
+void _font_color_selector_callback(void *data, const char *msg, void *event)
+{
+ text_editor_t *te = (text_editor_t *)data;
+ if (strcmp(msg, "layout") == 0) {
+ elm_object_part_content_set(te->body_main, "elm.swallow.tool", (Evas_Object *)event);
+ } else if (strcmp(msg, "change") == 0) {
+ LOGD("%s : %x\n", msg, (int)event);
+ te->record->font_color = (int)event;
+ _entry_content_update(te);
+ } else if (strcmp(msg, "flick,down") == 0) {
+ _font_color_selector_del(te);
+ edje_object_signal_emit(elm_layout_edje_get(te->body_main), "expand", "elm");
+ }
+}
+
+static void _font_color_selector_del(text_editor_t *te)
+{
+ if (te->h_fcs != NULL) {
+ elm_object_part_content_unset(te->body_main, "elm.swallow.tool");
+ memo_del_color_selector(te->h_fcs);
+ memo_tool_btn_focus_set(te->btn_color, EINA_FALSE);
+ te->h_fcs = NULL;
+ }
+}
+
+static void _on_font_color_btn_up(void *data, Evas *e, Evas_Object *evas_obj, void *event_info)
+{
+ text_editor_t *te = (text_editor_t *)data;
+ if (te->h_fcs!= NULL) { /* font color selector already open */
+ return;
+ }
+ if (te->h_fss!= NULL) { /* destroy font size selector */
+ _font_size_selector_del(te);
+ }
+ /* load font color selector */
+ service_h service = NULL;
+ service_create(&service);
+ snprintf(te->buf, MEMO_BUFFER_SIZE, "%d", te->record->font_color);
+ service_add_extra_data(service, "color", te->buf);
+ snprintf(te->buf, MEMO_BUFFER_SIZE, "%d", 0xFFFFFFFF);
+ service_add_extra_data(service, "bg_color", te->buf);
+ te->h_fcs = memo_load_color_selector(te->body_main, service, _font_color_selector_callback, te);
+ service_destroy(service);
+ memo_tool_btn_focus_set(te->btn_color, EINA_TRUE);
+ edje_object_signal_emit(elm_layout_edje_get(te->body_main), "abbrev", "elm");
+ /* hide input panel */
+ ecore_imf_context_input_panel_hide(te->imf_context);
+}
+
+static void _input_panel_event_callback(void *data, Ecore_IMF_Context *ctx, int value)
+{
+ text_editor_t *te = (text_editor_t *)data;
+ if (value == ECORE_IMF_INPUT_PANEL_STATE_HIDE) {
+ if ((te->h_fss==NULL) && (te->h_fcs==NULL)) { /* hide by sweep donw */
+ edje_object_signal_emit(elm_layout_edje_get(te->body_main), "expand", "elm");
+ }
+ } else if (value == ECORE_IMF_INPUT_PANEL_STATE_SHOW) {
+ edje_object_signal_emit(elm_layout_edje_get(te->body_main), "abbrev", "elm");
+ }
+}
+
+static void _on_entry_clicked(void *data, Evas_Object *obj, void *event_info)
+{
+ text_editor_t *te = (text_editor_t *)data;
+ if (te->h_fss!= NULL) { /* destroy font size selector */
+ _font_size_selector_del(te);
+ }
+ if (te->h_fcs != NULL) { /* destroy font color selector */
+ _font_color_selector_del(te);
+ }
+}
+
+static void _on_entry_content_change(void *data, Evas_Object *obj, void *event_info)
+{
+ text_editor_t *te = (text_editor_t *)data;
+ unsigned char *color = (unsigned char *)&te->record->font_color;
+
+ const char *text = elm_entry_entry_get(te->entry);
+ char *content = elm_entry_markup_to_utf8(text);
+ te->savable = EINA_TRUE;
+ if (strcmp(content, "") == 0) {
+ te->savable = EINA_FALSE;
+ } else if (te->record->content != NULL) { /* check if same as init string */
+ if ((te->init_fsize==te->record->font_size)
+ && (te->init_fcolor==te->record->font_color)
+ && (strcmp(te->record->content, content)==0)) {
+ te->savable = EINA_FALSE;
+ }
+ }
+ te->cb(te->data, "savable", (void *)(te->savable?1:0));
+
+ /* after paste/cut, the font size/color information may be cleared */
+ snprintf(te->buf, MEMO_BUFFER_SIZE, "<font_size=%d><color=#%02x%02x%02x>",
+ te->record->font_size, color[2], color[1], color[0]);
+ if (text[0] == '\0') { /* no content */
+ elm_entry_entry_insert(te->entry, te->buf);
+ } else if (text[0] != '<') { /* insert font information */
+ elm_entry_cursor_begin_set(te->entry);
+ elm_entry_entry_insert(te->entry, te->buf);
+ elm_entry_cursor_end_set(te->entry);
+ }
+ SFREE(content);
+}
+
+static void _on_yes(void *data, Evas_Object *obj, void *event_info)
+{
+ text_editor_t *te = (text_editor_t *)data;
+ _save_record(te);
+ te->cb(te->data, "drawing", NULL);
+}
+
+static void _on_no(void *data, Evas_Object *obj, void *event_info)
+{
+ text_editor_t *te = (text_editor_t *)data;
+ te->cb(te->data, "drawing", NULL);
+}
+
+static void _on_drawing_mode(void *data, Evas_Object *obj, void *event_info)
+{
+ text_editor_t *te = (text_editor_t *)data;
+ if (te->savable) { /* modified, need user confirmation */
+ memo_create_yes_no_popup(te->parent, MEMO_I18N_SAVE_MEMO, _on_yes, _on_no, te);
+ } else {
+ te->cb(te->data, "drawing", NULL);
+ }
+}
+
+static void _create_text_editor_layout(text_editor_t *te, service_h service)
+{
+ te->body_main = elm_layout_create(te->parent, EDJ_FILE, "text_editor");
+ te->cb(te->data, "layout", te->body_main);
+ /* title */
+ te->cb(te->data, "title", te->record->id==-1 ? MEMO_I18N_NEW_NOTE : MEMO_I18N_EDIT_NOTE);
+ /* date */
+ memo_time_format(te->buf, MEMO_BUFFER_SIZE, te->record->modi_time);
+ edje_object_part_text_set(elm_layout_edje_get(te->body_main), "elm.text.date", te->buf);
+ /* toolbar */
+ te->toolbar = elm_swallowed_layout(te->body_main, "elm.swallow.toolbar", EDJ_FILE, "edit_toolbar");
+ te->btn_size = elm_swallowed_layout(te->toolbar, "elm.swallow.btn1", EDJ_DIR"/white/memo.edj", "tl_font_size");
+ evas_object_event_callback_add(te->btn_size, EVAS_CALLBACK_MOUSE_UP, _on_font_size_btn_up, te);
+ te->btn_color = elm_swallowed_layout(te->toolbar, "elm.swallow.btn2", EDJ_DIR"/white/memo.edj", "tl_font_color");
+ evas_object_event_callback_add(te->btn_color, EVAS_CALLBACK_MOUSE_UP, _on_font_color_btn_up, te);
+ if (!service_key_check(service, "toggle", "disable")) {
+ elm_swallowed_button(te->toolbar, "elm.swallow.btn4", MEMO_I18N_DRAWING, _on_drawing_mode, te);
+ }
+ /* entry */
+ Evas_Object *sc = elm_swallowed_scroller(te->body_main, "elm.swallow.text");
+ unsigned char *color = (unsigned char *)&te->record->font_color;
+ snprintf(te->buf, MEMO_BUFFER_SIZE, "<font_size=%d><color=#%02x%02x%02x>",
+ te->record->font_size, color[2], color[1], color[0]);
+ te->entry = elm_entry_create(te->body_main, te->buf);
+ elm_entry_input_panel_enabled_set(te->entry, EINA_TRUE);
+ evas_object_size_hint_align_set(te->entry, EVAS_HINT_FILL, EVAS_HINT_FILL);
+ evas_object_size_hint_weight_set(te->entry, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+ elm_entry_autocapital_type_set(te->entry, ELM_AUTOCAPITAL_TYPE_SENTENCE);
+ elm_object_content_set(sc, te->entry);
+ evas_object_smart_callback_add(te->entry, "changed", _on_entry_content_change, te);
+ evas_object_smart_callback_add(te->entry, "preedit,changed", _on_entry_content_change, te);
+ evas_object_smart_callback_add(te->entry, "clicked", _on_entry_clicked, te);
+ /* limit size */
+ elm_entry_markup_filter_append(te->entry, elm_entry_filter_limit_size, &te->limit_filter_data);
+ /* entry content */
+ if (te->record->content != NULL) {
+ char *content = elm_entry_utf8_to_markup(te->record->content);
+ elm_entry_entry_insert(te->entry, content);
+ SFREE(content);
+ } else { /* set init string */
+ char *str = NULL;
+ service_get_extra_data(service, "init_str", &str);
+ if (str != NULL) {
+ elm_entry_entry_insert(te->entry, str);
+ SFREE(str);
+ }
+ }
+ elm_object_focus_set(te->entry, EINA_TRUE);
+ /* imf context */
+ te->imf_context = elm_entry_imf_context_get(te->entry);
+ ecore_imf_context_input_panel_event_callback_add(te->imf_context,
+ ECORE_IMF_INPUT_PANEL_STATE_EVENT, _input_panel_event_callback, te);
+ /* savable */
+ te->cb(te->data, "savable", (void *)(te->savable?1:0));
+}
+
+void memo_text_editor_time_format_update(void *h_te)
+{
+ text_editor_t *te = (text_editor_t *)h_te;
+ memo_time_format(te->buf, MEMO_BUFFER_SIZE, te->record->modi_time);
+ edje_object_part_text_set(elm_layout_edje_get(te->body_main), "elm.text.date", te->buf);
+}
+
+void memo_text_editor_cancel(void *h_te)
+{
+ text_editor_t *te = (text_editor_t *)h_te;
+ if (!te->savable) { /* not modified, return directly */
+ te->cb(te->data, "cancel", NULL);
+ } else {
+ /* hide imf, otherwise popup will be covered by imf */
+ if (te->imf_context != NULL) {
+ ecore_imf_context_input_panel_hide(te->imf_context);
+ }
+ _launch_yes_no_popup(te);
+ }
+}
+void memo_text_editor_save(void *h_te)
+{
+ text_editor_t *te = (text_editor_t *)h_te;
+ service_create(&text_service);
+ service_add_extra_data(text_service, "ug_text", te->data);
+ _save_record(te);
+ te->cb(te->data, "save", NULL);
+}
+
+void *memo_load_text_editor(Evas_Object *win, Evas_Object *parent, service_h service, Memo_Component_Callback cb, void *data)
+{
+ text_editor_t *te = SMALLOC(text_editor_t);
+ RETVIF(te==NULL, NULL);
+ service_dump(service);
+ te->win = win;
+ te->parent = parent;
+ te->cb = (cb==NULL ? memo_com_dummy_cb : cb); /* make sure cb is not null, no need to check legitimacy of cb when call */
+ te->data = data;
+
+ /* init */
+ const char *s = NULL;
+ service_get_extra_data(service, "index", &s);
+ if (s == NULL) {
+ te->record = memo_create_data();
+ te->record->id = -1;
+ te->record->modi_time = time((time_t *) 0);
+ te->record->font_size = 44;
+ te->record->font_color = 0xff000000;
+ } else { /* load item */
+ te->record = memo_get_data(atoi(s));
+ SFREE(s);
+ }
+ te->init_fsize = te->record->font_size;
+ te->init_fcolor = te->record->font_color;
+ /* limitation */
+ te->limit_filter_data.max_char_count = 0;
+ te->limit_filter_data.max_byte_count = 1000;
+
+ _create_text_editor_layout(te, service);
+ return (void *)te;
+}
+
+void memo_destroy_text_editor(void *h_te)
+{
+ text_editor_t *te = (text_editor_t *)h_te;
+ ecore_imf_context_input_panel_event_callback_del(te->imf_context,
+ ECORE_IMF_INPUT_PANEL_STATE_EVENT, _input_panel_event_callback);
+ ecore_imf_context_input_panel_hide(te->imf_context);
+ if (te->h_fss!= NULL) { /* destroy font size selector */
+ _font_size_selector_del(te);
+ }
+ if (te->h_fcs != NULL) { /* destroy font color selector */
+ _font_color_selector_del(te);
+ }
+ memo_free_data(te->record);
+ evas_object_del(te->body_main);
+ SFREE(te);
+}