diff options
Diffstat (limited to 'src/memo_text_editor.c')
-rw-r--r-- | src/memo_text_editor.c | 420 |
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); +} |