edc_editor: add pair of bracket highlighting feature

Summary: when mouse cursor on bracket which are '{', '}', the bracket is highlighted with its pair.

Reviewers: Jaehyun_Cho, Hermet

Reviewed By: Hermet

Subscribers: herb, NikaWhite, Jaehyun_Cho

Differential Revision: https://phab.enlightenment.org/D3588
This commit is contained in:
taehyub 2016-01-27 13:01:53 +09:00 committed by Hermet Park
parent f9edc4363d
commit ed7e655add
3 changed files with 364 additions and 2 deletions

View File

@ -175,6 +175,28 @@ error_highlight(edit_data *ed, Evas_Object *tb)
}
evas_textblock_cursor_free(cur1);
}
static void
bracket_highlight(edit_data *ed, Evas_Object *tb)
{
Evas_Textblock_Cursor *cur1 = evas_object_textblock_cursor_new(tb);
int left_bracket = parser_left_bracket_pos_get(ed->pd);
int right_bracket = parser_right_bracket_pos_get(ed->pd);
evas_textblock_cursor_pos_set(cur1, left_bracket);
evas_object_textblock_text_markup_prepend(cur1, "<hilight><color=#B1B1B1FF>");
evas_textblock_cursor_pos_set(cur1, left_bracket+1);
evas_object_textblock_text_markup_prepend(cur1, "</color></hilight>");
evas_textblock_cursor_pos_set(cur1, right_bracket);
evas_object_textblock_text_markup_prepend(cur1, "<hilight><color=#B1B1B1FF>");
evas_textblock_cursor_pos_set(cur1, right_bracket+1);
evas_object_textblock_text_markup_prepend(cur1, "</color></hilight>");
evas_textblock_cursor_free(cur1);
}
static void
syntax_color_apply(edit_data *ed, Eina_Bool partial)
{
@ -202,6 +224,7 @@ syntax_color_apply(edit_data *ed, Eina_Bool partial)
Logically that's unnecessary in this case. */
evas_object_textblock_text_markup_set(tb, translated);
error_highlight(ed, tb);
bracket_highlight(ed, tb);
entry_recover(ed, pos);
}
@ -269,6 +292,50 @@ syntax_color_thread_cancel_cb(void *data, Ecore_Thread *thread EINA_UNUSED)
free(td);
}
void
bracket_changed_cb(void *data)
{
edit_data *ed = data;
syntax_color_partial_update(ed, SYNTAX_COLOR_SHORT_TIME);
}
static void
bracket_update(edit_data *ed)
{
int pos = elm_entry_cursor_pos_get(ed->en_edit);
if (pos == 0) return;
Evas_Object *tb = elm_entry_textblock_get(ed->en_edit);
Evas_Textblock_Cursor *cur1 = evas_object_textblock_cursor_get(tb);
char ch1, ch2;
ch1 = -1;
ch2 = -1;
ch1 = evas_textblock_cursor_content_get(cur1)[0];
Eina_Bool is_exist = evas_textblock_cursor_char_prev(cur1);
if (is_exist)
ch2 = evas_textblock_cursor_content_get(cur1)[0];
evas_textblock_cursor_char_next(cur1);
if (ch1 != '{' && ch1 != '}' && ch2 != '{' && ch2 != '}')
{
int prev_left_bracket = parser_prev_left_bracket_pos_get(ed->pd);
int prev_right_bracket = parser_prev_right_bracket_pos_get(ed->pd);
if (prev_left_bracket != -1 && prev_right_bracket != -1)
{
parser_left_bracket_pos_set(ed->pd, -1);
parser_right_bracket_pos_set(ed->pd, -1);
parser_prev_left_bracket_pos_set(ed->pd, -1);
parser_prev_right_bracket_pos_set(ed->pd, -1);
syntax_color_partial_update(ed, SYNTAX_COLOR_SHORT_TIME);
}
return;
}
parser_bracket_pair_find(ed->pd, ed->en_edit, bracket_changed_cb, ed);
}
static void
edit_changed_cb(void *data, Evas_Object *obj EINA_UNUSED, void *event_info)
{
@ -324,8 +391,11 @@ edit_changed_cb(void *data, Evas_Object *obj EINA_UNUSED, void *event_info)
if (info->change.del.content[0] == ' ') return;
}
if (!syntax_color) return;
syntax_color_partial_update(ed, SYNTAX_COLOR_DEFAULT_TIME);
parser_bracket_pair_cancel(ed->pd);
}
static void
@ -730,6 +800,8 @@ edit_cursor_changed_cb(void *data, Evas_Object *obj EINA_UNUSED,
edit_data *ed = data;
cur_line_pos_set(ed, EINA_FALSE);
edit_view_sync(ed);
bracket_update(ed);
}
static void

View File

@ -52,6 +52,22 @@ typedef struct type_init_thread_data_s
parser_data *pd;
} type_init_td;
typedef struct bracket_data_s
{
int left;
int right;
int prev_left;
int prev_right;
} bracket;
typedef struct bracket_thread_data_s
{
int pos;
const char *text;
Bracket_Update_Cb update_cb;
void *data;
} bracket_data_td;
struct parser_s
{
Eina_Inarray *attrs;
@ -59,10 +75,15 @@ struct parser_s
type_init_td *titd;
Eina_List *macro_list;
bracket_data_td *bracket_td;
Ecore_Thread *bracket_thread;
bracket bracket_pos;
Eina_Bool is_bracket_thread_req: 1;
Eina_Bool macro_update : 1;
};
/*****************************************************************************/
/* Internal method implementation */
/*****************************************************************************/
@ -1857,6 +1878,8 @@ parser_init(void)
td->pd = pd;
pd->titd = td;
pd->bracket_pos.left = -1;
pd->bracket_pos.right = -1;
td->thread = ecore_thread_run(type_init_thread_blocking,
type_init_thread_end,
type_init_thread_cancel, td);
@ -1949,3 +1972,260 @@ parser_macro_update(parser_data *pd, Eina_Bool macro_update)
{
pd->macro_update = macro_update;
}
static Eina_Bool
bracket_pair_parse(int pos, const char *text, int *left, int *right)
{
int left_bracket = -1;
int right_bracket = -1;
int cur_pos = pos;
int depth = 0;
if (cur_pos == 0)
return EINA_FALSE;
const char *utf8 = text;
int length = strlen(utf8);
// left, {
if (utf8[cur_pos] == '{')
{
left_bracket = cur_pos;
cur_pos++;
while (cur_pos < length)
{
if (utf8[cur_pos] == '{') depth++;
else if (utf8[cur_pos] == '}')
{
if (depth) depth--;
else
{
right_bracket = cur_pos;
break;
}
}
cur_pos++;
}
}
// left, }
else if(utf8[cur_pos] == '}')
{
right_bracket = cur_pos;
cur_pos--;
while (cur_pos)
{
if (utf8[cur_pos] == '}') depth++;
else if(utf8[cur_pos] == '{')
{
if(depth) depth--;
else
{
left_bracket = cur_pos;
break;
}
}
cur_pos--;
}
}
// right, {
else if(utf8[cur_pos - 1] == '{')
{
left_bracket = cur_pos - 1;
while (cur_pos < length)
{
if (utf8[cur_pos] == '{') depth++;
else if (utf8[cur_pos] == '}')
{
if (depth) depth--;
else
{
right_bracket = cur_pos;
break;
}
}
cur_pos++;
}
}
// right, }
else if(utf8[cur_pos - 1] == '}')
{
right_bracket = cur_pos - 1;
cur_pos -= 2;
while (cur_pos)
{
if (utf8[cur_pos] == '}') depth++;
else if (utf8[cur_pos] == '{')
{
if(depth) depth--;
else
{
left_bracket = cur_pos;
break;
}
}
cur_pos--;
}
}
if (left_bracket == -1 || right_bracket == -1)
{
left_bracket = -1;
right_bracket = -1;
}
*left = left_bracket;
*right = right_bracket;
return EINA_TRUE;
}
static void bracket_thread_cb(void *data, Ecore_Thread *thread EINA_UNUSED);
static void bracket_thread_end_cb(void *data, Ecore_Thread *thread EINA_UNUSED);
static void bracket_thread_cancel_cb(void *data, Ecore_Thread *thread EINA_UNUSED);
static void
bracket_thread_cb(void *data, Ecore_Thread *thread EINA_UNUSED)
{
parser_data *pd = data;
if (bracket_pair_parse(pd->bracket_td->pos, pd->bracket_td->text,
&(pd->bracket_pos.left),
&(pd->bracket_pos.right)) == EINA_FALSE)
return;
if (pd->bracket_pos.left != -1 && pd->bracket_pos.right != -1)
{
if (pd->bracket_pos.prev_left != pd->bracket_pos.left
&& pd->bracket_pos.prev_right != pd->bracket_pos.right)
{
pd->bracket_td->update_cb(pd->bracket_td->data);
pd->bracket_pos.prev_left = pd->bracket_pos.left;
pd->bracket_pos.prev_right = pd->bracket_pos.right;
}
}
else if(pd->bracket_pos.prev_left != -1 && pd->bracket_pos.prev_right != -1)
{
pd->bracket_td->update_cb(pd->bracket_td->data);
pd->bracket_pos.prev_left = -1;
pd->bracket_pos.prev_right = -1;
}
}
static void
bracket_thread_end_cb(void *data, Ecore_Thread *thread EINA_UNUSED)
{
parser_data *pd = data;
if (pd->is_bracket_thread_req == EINA_TRUE)
{
pd->is_bracket_thread_req = EINA_FALSE;
pd->bracket_thread = ecore_thread_run(bracket_thread_cb,
bracket_thread_end_cb,
bracket_thread_cancel_cb,
pd);
}
else
{
free(pd->bracket_td);
pd->bracket_td = NULL;
pd->bracket_thread = NULL;
}
}
static void
bracket_thread_cancel_cb(void *data, Ecore_Thread *thread EINA_UNUSED)
{
parser_data *pd = data;
if (pd->is_bracket_thread_req == EINA_TRUE)
{
pd->is_bracket_thread_req = EINA_FALSE;
pd->bracket_thread = ecore_thread_run(bracket_thread_cb,
bracket_thread_end_cb,
bracket_thread_cancel_cb,
pd);
}
else
{
free(pd->bracket_td);
pd->bracket_td = NULL;
pd->bracket_thread = NULL;
}
}
void
parser_bracket_pair_find(parser_data *pd, Evas_Object *entry,
Bracket_Update_Cb func, void *data)
{
ecore_thread_cancel(pd->bracket_thread);
if (pd->bracket_td == NULL)
pd->bracket_td = calloc(1, sizeof(bracket_data_td));
const char *text = elm_entry_entry_get(entry);
char *utf8 = elm_entry_markup_to_utf8(text);
int pos = elm_entry_cursor_pos_get(entry);
pd->bracket_td->pos = pos;
pd->bracket_td->text = utf8;
pd->bracket_td->update_cb = func;
pd->bracket_td->data = data;
if (pd->bracket_thread == NULL)
{
pd->is_bracket_thread_req = EINA_FALSE;
pd->bracket_thread = ecore_thread_run(bracket_thread_cb,
bracket_thread_end_cb,
bracket_thread_cancel_cb,
pd);
}
else
pd->is_bracket_thread_req = EINA_TRUE;
}
void parser_bracket_pair_cancel(parser_data *pd)
{
ecore_thread_cancel(pd->bracket_thread);
}
void parser_left_bracket_pos_set(parser_data *pd, int pos)
{
pd->bracket_pos.left = pos;
}
void parser_right_bracket_pos_set(parser_data *pd, int pos)
{
pd->bracket_pos.right = pos;
}
void parser_prev_left_bracket_pos_set(parser_data *pd, int pos)
{
pd->bracket_pos.prev_left = pos;
}
void parser_prev_right_bracket_pos_set(parser_data *pd, int pos)
{
pd->bracket_pos.prev_right = pos;
}
int parser_left_bracket_pos_get(parser_data *pd)
{
return pd->bracket_pos.left;
}
int parser_right_bracket_pos_get(parser_data *pd)
{
return pd->bracket_pos.right;
}
int parser_prev_left_bracket_pos_get(parser_data *pd)
{
return pd->bracket_pos.prev_left;
}
int parser_prev_right_bracket_pos_get(parser_data *pd)
{
return pd->bracket_pos.prev_right;
}

View File

@ -139,7 +139,17 @@ Eina_Bool parser_state_info_get(Evas_Object *entry, state_info *info);
void parser_macro_list_set(parser_data *pd, const char *text);
Eina_List *parser_macro_list_get(parser_data *pd);
void parser_macro_update(parser_data *pd, Eina_Bool macro_update);
typedef void (*Bracket_Update_Cb)(void *data);
void parser_bracket_pair_find(parser_data *pd, Evas_Object *entry, Bracket_Update_Cb func, void *data);
void parser_bracket_pair_cancel(parser_data *pd);
void parser_left_bracket_pos_set(parser_data *pd, int pos);
void parser_right_bracket_pos_set(parser_data *pd, int pos);
void parser_prev_left_bracket_pos_set(parser_data *pd, int pos);
void parser_prev_right_bracket_pos_set(parser_data *pd, int pos);
int parser_left_bracket_pos_get(parser_data *pd);
int parser_right_bracket_pos_get(parser_data *pd);
int parser_prev_left_bracket_pos_get(parser_data *pd);
int parser_prev_right_bracket_pos_get(parser_data *pd);
/* syntax helper */
syntax_helper *syntax_init(void);