Enlightenment CVS committal Author : moom Project : e17 Module : proto
Dir : e17/proto/etk/src/lib Modified Files: etk_text_view.c etk_textblock.c etk_textblock.h Log Message: * More TB work: start the selection code =================================================================== RCS file: /cvs/e/e17/proto/etk/src/lib/etk_text_view.c,v retrieving revision 1.9 retrieving revision 1.10 diff -u -3 -r1.9 -r1.10 --- etk_text_view.c 10 Jul 2006 03:26:53 -0000 1.9 +++ etk_text_view.c 22 Jul 2006 15:32:07 -0000 1.10 @@ -158,16 +158,26 @@ { Etk_Text_View *text_view; Etk_Textblock_Iter *cursor; + Etk_Textblock_Iter *selection; if (!(text_view = ETK_TEXT_VIEW(object)) || !event || !text_view->textblock_object) return; cursor = etk_textblock_object_cursor_get(text_view->textblock_object); + selection = etk_textblock_object_selection_bound_get(text_view->textblock_object); if (strcmp(event->key, "Left") == 0) + { etk_textblock_iter_backward_char(cursor); + if (!evas_key_modifier_is_set(event->modifiers, "Shift")) + etk_textblock_iter_copy(selection, cursor); + } else if (strcmp(event->key, "Right") == 0) + { etk_textblock_iter_forward_char(cursor); + if (!evas_key_modifier_is_set(event->modifiers, "Shift")) + etk_textblock_iter_copy(selection, cursor); + } else if (strcmp(event->key, "Return") == 0 || strcmp(event->key, "KP_Enter") == 0) etk_textblock_text_insert(text_view->textblock, cursor, "\n", -1); else if (event->string && !(strlen(event->string) == 1 && event->string[0] < 0x20)) =================================================================== RCS file: /cvs/e/e17/proto/etk/src/lib/etk_textblock.c,v retrieving revision 1.20 retrieving revision 1.21 diff -u -3 -r1.20 -r1.21 --- etk_textblock.c 21 Jul 2006 00:31:30 -0000 1.20 +++ etk_textblock.c 22 Jul 2006 15:32:07 -0000 1.21 @@ -13,7 +13,8 @@ * @{ */ -#define ETK_TB_OBJECT_HEIGHT 300 +#define ETK_TB_OBJECT_DEFAULT_HEIGHT 300 +#define ETK_TB_EMPTY_LINE_WIDTH 3 #define ETK_TB_OBJECT_SHOW_CURSOR_DELAY 0.75 #define ETK_TB_OBJECT_HIDE_CURSOR_DELAY 0.25 @@ -37,14 +38,20 @@ Etk_Textblock_Object_Line *lines; Etk_Textblock_Object_Line *last_line; + Etk_Textblock_Object_Line *first_visible_line; + Etk_Textblock_Object_Line *last_visible_line; Etk_Bool cursor_visible; Etk_Textblock_Iter *cursor; Etk_Textblock_Iter *selection; Evas_Object *cursor_object; + Evas_List *selection_rects; Evas_Object *clip; + int xoffset; + int yoffset; + Ecore_Timer *cursor_timer; Ecore_Job *update_job; }; @@ -121,6 +128,8 @@ static Evas_Textblock_Cursor *_etk_textblock_object_cursor_get_from_iter(Evas_Object *tbo, Etk_Textblock_Iter *iter); static int _etk_textblock_text_nodes_count(Etk_Textblock_Node *line, Etk_Textblock_Node *node); +static Evas_List *_etk_textblock_object_range_geometry_get(Evas_Object *tbo, Etk_Textblock_Iter *start, Etk_Textblock_Iter *end); + static void _etk_tb_object_smart_add(Evas_Object *obj); static void _etk_tb_object_smart_del(Evas_Object *obj); static void _etk_tb_object_smart_move(Evas_Object *obj, Evas_Coord x, Evas_Coord y); @@ -358,7 +367,7 @@ node_start = i; unicode_length++; - /* If we have parsed a full node, a escape sequence or a "end of line" sequence, we insert the text or + /* If we have parsed a full node, a escape sequence or a end-of-line sequence, we insert the text or * we create a new line */ if ((node_start >= 0 && node_end >= 0) || (esc_start >= 0 && esc_end >= 0) || new_line) { @@ -634,6 +643,7 @@ * @return Returns ETK_FALSE if the movement was not possible (i.e. if the iterator already points * on the first character of the textblock) */ +/* TODO: improve placement */ Etk_Bool etk_textblock_iter_backward_char(Etk_Textblock_Iter *iter) { if (!(iter || !_etk_textblock_iter_is_valid(NULL, iter))) @@ -669,6 +679,7 @@ * @return Returns ETK_FALSE if the movement was not possible (i.e. if the iterator already points * after the last character of the textblock) */ +/* TODO: improve placement */ Etk_Bool etk_textblock_iter_forward_char(Etk_Textblock_Iter *iter) { if (!(iter || !_etk_textblock_iter_is_valid(NULL, iter))) @@ -848,10 +859,10 @@ evas_textblock_cursor_format_append(cur, "+ wrap=none"); evas_textblock_cursor_node_prev(cur); evas_textblock_cursor_node_delete(cur); - evas_textblock_cursor_free(cur); break; } } + evas_textblock_cursor_free(cur); _etk_textblock_object_line_update_queue(tbo, line, ETK_FALSE, ETK_TRUE); } @@ -949,7 +960,6 @@ return tbo_sd->selection; } - /************************** * Misc funcs **************************/ @@ -1317,6 +1327,7 @@ } /* Removes the empty nodes in the list of 'nodes' */ +/* TODO: do not clean empty lines and implement _etk_textblock_nodes_range_clean() */ static void _etk_textblock_nodes_clean(Etk_Textblock *tb, Etk_Textblock_Node *nodes) { Etk_Textblock_Node *n; @@ -1877,6 +1888,7 @@ } /* Compares the two nodes. */ +/* TODO: OPTIMIZE this!!! Use a binary tree for the lines! */ static int _etk_textblock_node_compare(Etk_Textblock_Node *node1, Etk_Textblock_Node *node2) { Etk_Textblock_Node *p1, *p2; @@ -1893,6 +1905,7 @@ c2 = node2; for (p1 = node1->parent; p1; p1 = p1->parent) { + c2 = node2; for (p2 = node2->parent; p2; p2 = p2->parent) { if (p1 == p2) @@ -2883,7 +2896,7 @@ if (line->need_geometry_update) { - evas_object_resize(line->object, line->geometry.w, ETK_TB_OBJECT_HEIGHT); + evas_object_resize(line->object, line->geometry.w, ETK_TB_OBJECT_DEFAULT_HEIGHT); evas_object_textblock_size_formatted_get(line->object, NULL, &line->geometry.h); line->need_geometry_update = ETK_FALSE; @@ -2919,21 +2932,66 @@ /* Updates the cursor object and the selection of the textblock object */ static void _etk_textblock_object_cursor_update(Evas_Object *tbo) { + Evas *evas; Etk_Textblock_Object_SD *tbo_sd; Evas_Textblock_Cursor *cur; Etk_Textblock_Object_Line *line; + Evas_List *selection_geometry; + Etk_Geometry *rect_geometry; + Evas_Object *rect; + int visible; /* TODO: valg? */ int cx = 0, cy = 0, cw = 0, ch = 0; int ox, oy; + int res; - if (!tbo || !(tbo_sd = evas_object_smart_data_get(tbo))) + if (!tbo || !(tbo_sd = evas_object_smart_data_get(tbo)) || !(evas = evas_object_evas_get(tbo))) return; + visible = evas_object_visible_get(tbo); + evas_object_geometry_get(tbo, &ox, &oy, NULL, NULL); + + /* Update the selection */ + /* TODO: selection stacking ?! */ + while (tbo_sd->selection_rects) + { + evas_object_del(tbo_sd->selection_rects->data); + tbo_sd->selection_rects = evas_list_remove_list(tbo_sd->selection_rects, tbo_sd->selection_rects); + } + res = etk_textblock_iter_compare(tbo_sd->cursor, tbo_sd->selection); + if (res != 0) + { + if (res < 0) + selection_geometry = _etk_textblock_object_range_geometry_get(tbo, tbo_sd->cursor, tbo_sd->selection); + else + selection_geometry = _etk_textblock_object_range_geometry_get(tbo, tbo_sd->selection, tbo_sd->cursor); + + while (selection_geometry) + { + rect_geometry = selection_geometry->data; + + rect = evas_object_rectangle_add(evas); + /* TODO: make the selection themeable */ + evas_object_color_set(rect, 245, 205, 109, 102); + evas_object_move(rect, ox + rect_geometry->x, oy + rect_geometry->y); + evas_object_resize(rect, rect_geometry->w, rect_geometry->h); + evas_object_clip_set(rect, tbo_sd->clip); + evas_object_smart_member_add(rect, tbo); + if (visible) + evas_object_show(rect); + + free(rect_geometry); + tbo_sd->selection_rects = evas_list_append(tbo_sd->selection_rects, rect); + selection_geometry = evas_list_remove_list(selection_geometry, selection_geometry); + } + } + + + /* Update the cursor */ line = _etk_textblock_object_line_get_from_node(tbo, tbo_sd->cursor->node); /* TODO: optimize?! */ cur = _etk_textblock_object_cursor_get_from_iter(tbo, tbo_sd->cursor); evas_textblock_cursor_char_geometry_get(cur, &cx, &cy, &cw, &ch); - evas_object_geometry_get(tbo, &ox, &oy, NULL, NULL); /* TODO: make sure the cursor is visible?! */ if (tbo_sd->cursor->pos < tbo_sd->cursor->node->unicode_length) @@ -2956,6 +3014,9 @@ if (!tbo || !(tbo_sd = evas_object_smart_data_get(tbo))) return; + tbo_sd->first_visible_line = NULL; + tbo_sd->last_visible_line = NULL; + /* We update the lines */ /* TODO: optimize: Updates all the lines in several times and use a btree! */ y = 0; @@ -2976,6 +3037,10 @@ evas_object_move(line->object, ox + line->geometry.x, oy + line->geometry.y); evas_object_resize(line->object, line->geometry.w, line->geometry.h); evas_object_show(line->object); + + if (!tbo_sd->first_visible_line) + tbo_sd->first_visible_line = line; + tbo_sd->last_visible_line = line; } } @@ -3119,6 +3184,125 @@ return count; } + +/* Gets a list of Etk_Geometry's corresponding to the geometry of the text between @a start and @a end. + * The items of the returned list should be freed, and the list should be destroyed manually. + * Only the visible lines are stored in the list. */ +static Evas_List *_etk_textblock_object_range_geometry_get(Evas_Object *tbo, Etk_Textblock_Iter *start, Etk_Textblock_Iter *end) +{ + Etk_Textblock_Object_SD *tbo_sd; + Etk_Textblock_Object_Line *line, *start_line, *end_line; + Evas_List *selection_geometry = NULL; + Etk_Geometry *rect_geometry; + Etk_Bool add_line; + Evas *evas; + + if (!tbo || !start || !end) + return NULL; + if (!(tbo_sd = evas_object_smart_data_get(tbo)) || !(evas = evas_object_evas_get(tbo))) + return NULL; + if (!tbo_sd->first_visible_line) + return NULL; + + if (_etk_textblock_node_compare(end->node, tbo_sd->first_visible_line->node) < 0) + return NULL; + + if (_etk_textblock_node_compare(start->node, tbo_sd->first_visible_line->node) <= 0) + add_line = ETK_TRUE; + else + add_line = ETK_FALSE; + + start_line = _etk_textblock_object_line_get_from_node(tbo, start->node); + end_line = _etk_textblock_object_line_get_from_node(tbo, end->node); + + for (line = tbo_sd->first_visible_line; line; line = line->next) + { + if (!add_line && line == start_line) + add_line = ETK_TRUE; + + /* We add the geometry of the line to the list */ + if (add_line) + { + Evas_List *rects; + Evas_Textblock_Rectangle *rect; + const char *font_face; + int font_size; + + if (_etk_textblock_node_is_empty_line(line->node, &font_face, &font_size)) + { + rect_geometry = malloc(sizeof(Etk_Geometry)); + rect_geometry->x = line->geometry.x; + rect_geometry->y = line->geometry.y; + rect_geometry->w = ETK_TB_EMPTY_LINE_WIDTH; + /* TODO: correct font, and align */ + etk_textblock_char_size_get(evas, "Vera", 10, NULL, &rect_geometry->h); + + selection_geometry = evas_list_append(selection_geometry, rect_geometry); + } + else if (line->object) + { + Evas_Textblock_Cursor *cur1, *cur2; + + cur1 = NULL; + /* TODO: optimize */ + if (line == start_line) + cur1 = _etk_textblock_object_cursor_get_from_iter(tbo, start); + if (!cur1) + { + cur1 = evas_object_textblock_cursor_new(line->object); + evas_textblock_cursor_node_first(cur1); + while (!evas_textblock_cursor_node_text_get(cur1)) + { + if (!evas_textblock_cursor_node_next(cur1)) + break; + } + evas_textblock_cursor_char_first(cur1); + } + + cur2 = NULL; + /* TODO: optimize */ + if (line == end_line) + { + cur2 = _etk_textblock_object_cursor_get_from_iter(tbo, end); + evas_textblock_cursor_char_prev(cur2); + } + if (!cur2) + { + cur2 = evas_object_textblock_cursor_new(line->object); + evas_textblock_cursor_node_last(cur2); + while (!evas_textblock_cursor_node_text_get(cur2)) + { + if (!evas_textblock_cursor_node_prev(cur2)) + break; + } + evas_textblock_cursor_char_last(cur2); + } + + rects = evas_textblock_cursor_range_geometry_get(cur1, cur2); + while (rects) + { + rect = rects->data; + + rect_geometry = malloc(sizeof(Etk_Geometry)); + rect_geometry->x = rect->x + line->geometry.x; + rect_geometry->y = rect->y + line->geometry.y; + rect_geometry->w = rect->w; + rect_geometry->h = rect->h; + selection_geometry = evas_list_append(selection_geometry, rect_geometry); + + free(rect); + rects = evas_list_remove_list(rects, rects); + } + } + } + + if (line == end_line) + break; + } + + return selection_geometry; +} + /************************** * * Textblock object's smart object @@ -3150,8 +3334,15 @@ evas_object_clip_set(tbo_sd->cursor_object, tbo_sd->clip); evas_object_smart_member_add(tbo_sd->cursor_object, obj); + tbo_sd->selection_rects = NULL; + tbo_sd->lines = NULL; tbo_sd->last_line = NULL; + tbo_sd->first_visible_line = NULL; + tbo_sd->last_visible_line = NULL; + + tbo_sd->xoffset = 0; + tbo_sd->yoffset = 0; tbo_sd->cursor = NULL; tbo_sd->selection = NULL; @@ -3176,6 +3367,11 @@ if (tbo_sd->update_job) ecore_job_del(tbo_sd->update_job); + while (tbo_sd->selection_rects) + { + evas_object_del(tbo_sd->selection_rects->data); + tbo_sd->selection_rects = evas_list_remove_list(tbo_sd->selection_rects, tbo_sd->selection_rects); + } for (line = tbo_sd->lines; line; line = next) { if (line->object) @@ -3202,9 +3398,10 @@ { Etk_Textblock_Object_SD *tbo_sd; int prev_x, prev_y; - int cursor_x, cursor_y; - int line_x, line_y; + int current_x, current_y; Etk_Textblock_Object_Line *line; + Evas_Object *selection_rect; + Evas_List *l; if (!obj || !(tbo_sd = evas_object_smart_data_get(obj))) return; @@ -3212,17 +3409,27 @@ evas_object_move(tbo_sd->clip, x, y); evas_object_geometry_get(obj, &prev_x, &prev_y, NULL, NULL); - for (line = tbo_sd->lines; line; line = line->next) + for (line = tbo_sd->first_visible_line; line; line = line->next) { if (line->object) { - evas_object_geometry_get(line->object, &line_x, &line_y, NULL, NULL); - evas_object_move(line->object, line_x + x - prev_x, line_y + y - prev_y); + evas_object_geometry_get(line->object, ¤t_x, ¤t_y, NULL, NULL); + evas_object_move(line->object, current_x + x - prev_x, current_y + y - prev_y); } + + if (line == tbo_sd->last_visible_line) + break; } - evas_object_geometry_get(tbo_sd->cursor_object, &cursor_x, &cursor_y, NULL, NULL); - evas_object_move(tbo_sd->cursor_object, cursor_x + x - prev_x, cursor_y + y - prev_y); + evas_object_geometry_get(tbo_sd->cursor_object, ¤t_x, ¤t_y, NULL, NULL); + evas_object_move(tbo_sd->cursor_object, current_x + x - prev_x, current_y + y - prev_y); + + for (l = tbo_sd->selection_rects; l; l = l->next) + { + selection_rect = l->data; + evas_object_geometry_get(selection_rect, ¤t_x, ¤t_y, NULL, NULL); + evas_object_move(selection_rect, current_x + x - prev_x, current_y + y - prev_y); + } } /* Resizes the textblock object */ @@ -3246,16 +3453,20 @@ { Etk_Textblock_Object_SD *tbo_sd; Etk_Textblock_Object_Line *line; + Evas_List *l; if (!obj || !(tbo_sd = evas_object_smart_data_get(obj))) return; evas_object_show(tbo_sd->clip); - for (line = tbo_sd->lines; line; line = line->next) + for (line = tbo_sd->first_visible_line; line; line = line->next) { if (line->object) evas_object_show(line->object); + + if (line == tbo_sd->last_visible_line) + break; } if (tbo_sd->cursor_visible) @@ -3269,6 +3480,9 @@ else ecore_timer_interval_set(tbo_sd->cursor_timer, ETK_TB_OBJECT_SHOW_CURSOR_DELAY); } + + for (l = tbo_sd->selection_rects; l; l = l->next) + evas_object_show(l->data); } /* Hides the textblock object */ @@ -3276,16 +3490,20 @@ { Etk_Textblock_Object_SD *tbo_sd; Etk_Textblock_Object_Line *line; + Evas_List *l; if (!obj || !(tbo_sd = evas_object_smart_data_get(obj))) return; evas_object_hide(tbo_sd->clip); - for (line = tbo_sd->lines; line; line = line->next) + for (line = tbo_sd->first_visible_line; line; line = line->next) { if (line->object) evas_object_hide(line->object); + + if (line == tbo_sd->last_visible_line) + break; } evas_object_hide(tbo_sd->cursor_object); @@ -3294,6 +3512,9 @@ ecore_timer_del(tbo_sd->cursor_timer); tbo_sd->cursor_timer = NULL; } + + for (l = tbo_sd->selection_rects; l; l = l->next) + evas_object_hide(l->data); } /* Set the color of the textblock object */ =================================================================== RCS file: /cvs/e/e17/proto/etk/src/lib/etk_textblock.h,v retrieving revision 1.12 retrieving revision 1.13 diff -u -3 -r1.12 -r1.13 --- etk_textblock.h 21 Jul 2006 00:31:30 -0000 1.12 +++ etk_textblock.h 22 Jul 2006 15:32:07 -0000 1.13 @@ -54,7 +54,7 @@ typedef enum Etk_Textblock_Style_Type { ETK_TEXTBLOCK_STYLE_NONE, /**< No style is applied */ - ETK_TEXTBLOCK_STYLE_OUTLINE, /**< The text is oulined */ + ETK_TEXTBLOCK_STYLE_OUTLINE, /**< The text is outlined */ ETK_TEXTBLOCK_STYLE_SHADOW, /**< The text has a sharp shadow */ ETK_TEXTBLOCK_STYLE_SOFT_OUTLINE, /**< The text has a soft outline */ ETK_TEXTBLOCK_STYLE_GLOW, /**< The text has a glow */ ------------------------------------------------------------------------- Take Surveys. Earn Cash. Influence the Future of IT Join SourceForge.net's Techsay panel and you'll get the chance to share your opinions on IT & business topics through brief surveys -- and earn cash http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV _______________________________________________ enlightenment-cvs mailing list enlightenment-cvs@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/enlightenment-cvs